223 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			223 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Created by WolverinDEV on 06/04/2020.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								#include <iostream>
							 | 
						||
| 
								 | 
							
								#include <bitset>
							 | 
						||
| 
								 | 
							
								#include <src/protocol/PacketLossCalculator.h>
							 | 
						||
| 
								 | 
							
								#include <cassert>
							 | 
						||
| 
								 | 
							
								#include <vector>
							 | 
						||
| 
								 | 
							
								#include <cmath>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using UnorderedPacketLossCalculator = ts::protocol::UnorderedPacketLossCalculator;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void print_unordered_stats(UnorderedPacketLossCalculator& generator) {
							 | 
						||
| 
								 | 
							
								    std::cout << "Valid data: " << generator.valid_data() << ". (Received{local: " << generator.received_packets() << ", unconfirmed: " << generator.unconfirmed_received_packets() << ", total: " << generator.received_packets_total() << "}" <<
							 | 
						||
| 
								 | 
							
								                                           " Lost: {local: " << generator.lost_packets() << ", unconfirmed: " << generator.unconfirmed_lost_packets() << ", total: " << generator.lost_packets_total() << "} Current ID: " << generator.last_packet_id() << ")\n";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename vector_t>
							 | 
						||
| 
								 | 
							
								vector_t swap_elements(vector_t vector, int per, int max_distance) {
							 | 
						||
| 
								 | 
							
								    for(size_t index = 0; index < vector.size() - max_distance; index++) {
							 | 
						||
| 
								 | 
							
								        if ((rand() % 100) < per) {
							 | 
						||
| 
								 | 
							
								            //lets switch
							 | 
						||
| 
								 | 
							
								            auto offset = rand() % max_distance;
							 | 
						||
| 
								 | 
							
								            std::swap(vector[index], vector[index + offset]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return vector;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void generate_unordered(UnorderedPacketLossCalculator& generator, int loss, size_t count) {
							 | 
						||
| 
								 | 
							
								    size_t id{generator.last_packet_id()};
							 | 
						||
| 
								 | 
							
								    while(count--) {
							 | 
						||
| 
								 | 
							
								        if(rand() % 100 >= loss)
							 | 
						||
| 
								 | 
							
								            generator.packet_received(id);
							 | 
						||
| 
								 | 
							
								        id++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_const_unordered_0() {
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								        generator.packet_received(pid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets_total() == 68);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_received_packets() == 32);
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets() == 68);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets_total() == 0);
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets() == 0);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_lost_packets() == 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.valid_data());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_const_unordered_1() {
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    generator.packet_received(100); /* we lost the first 99 packets */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets_total() == 0);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_received_packets() == 1);
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets() == 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets_total() == 68);
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets() == 68);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_lost_packets() == 31);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.valid_data());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_const_unordered_2() {
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								        if(pid % 2)
							 | 
						||
| 
								 | 
							
								            generator.packet_received(pid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets_total() == 34);
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets() == 34);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_received_packets() == 16);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets_total() == 34);
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets() == 34);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_lost_packets() == 16);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.valid_data());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_const_unordered_3() {
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								        if(pid % 3)
							 | 
						||
| 
								 | 
							
								            generator.packet_received(pid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets_total() == 44);
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets() == 44);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_received_packets() == 22);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets_total() == 23);
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets() == 23);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_lost_packets() == 10);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.valid_data());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_const_unordered_4() {
							 | 
						||
| 
								 | 
							
								    std::vector<uint32_t> received_packets{};
							 | 
						||
| 
								 | 
							
								    for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								        received_packets.push_back(pid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    received_packets = swap_elements(received_packets, 50, 7);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    for(const auto& packet : received_packets)
							 | 
						||
| 
								 | 
							
								        generator.packet_received(packet);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets_total() == 68);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_received_packets() == 32);
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets() == 68);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets_total() == 0);
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets() == 0);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_lost_packets() == 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.valid_data());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_const_unordered_5() {
							 | 
						||
| 
								 | 
							
								    std::vector<uint32_t> received_packets{};
							 | 
						||
| 
								 | 
							
								    for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								        if(pid % 3)
							 | 
						||
| 
								 | 
							
								            received_packets.push_back(pid);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    received_packets = swap_elements(received_packets, 30, 7);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    for(const auto& packet : received_packets)
							 | 
						||
| 
								 | 
							
								        generator.packet_received(packet);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets_total() == 44);
							 | 
						||
| 
								 | 
							
								    assert(generator.received_packets() == 44);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_received_packets() == 22);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets_total() == 23);
							 | 
						||
| 
								 | 
							
								    assert(generator.lost_packets() == 23);
							 | 
						||
| 
								 | 
							
								    assert(generator.unconfirmed_lost_packets() == 10);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert(generator.valid_data());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void test_unordered_6() {
							 | 
						||
| 
								 | 
							
								    UnorderedPacketLossCalculator generator{};
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const auto pid_base = generator.last_packet_id();
							 | 
						||
| 
								 | 
							
								        for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								            generator.packet_received(pid_base + pid);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    print_unordered_stats(generator);
							 | 
						||
| 
								 | 
							
								    generator.short_stats();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const auto pid_base = generator.last_packet_id();
							 | 
						||
| 
								 | 
							
								        generator.packet_received(pid_base + 100);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    print_unordered_stats(generator);
							 | 
						||
| 
								 | 
							
								    generator.short_stats();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const auto pid_base = generator.last_packet_id();
							 | 
						||
| 
								 | 
							
								        generator.packet_received(pid_base + 100);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    print_unordered_stats(generator);
							 | 
						||
| 
								 | 
							
								    generator.short_stats();
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const auto pid_base = generator.last_packet_id();
							 | 
						||
| 
								 | 
							
								        for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								            generator.packet_received(pid_base + pid);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    print_unordered_stats(generator);
							 | 
						||
| 
								 | 
							
								    generator.short_stats();
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        const auto pid_base = generator.last_packet_id();
							 | 
						||
| 
								 | 
							
								        for(size_t pid{0}; pid < 100; pid++)
							 | 
						||
| 
								 | 
							
								            generator.packet_received(pid_base + pid);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    print_unordered_stats(generator);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int main() {
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    test_const_unordered_0();
							 | 
						||
| 
								 | 
							
								    test_const_unordered_1();
							 | 
						||
| 
								 | 
							
								    test_const_unordered_2();
							 | 
						||
| 
								 | 
							
								    test_const_unordered_3();
							 | 
						||
| 
								 | 
							
								    test_const_unordered_4();
							 | 
						||
| 
								 | 
							
								    test_const_unordered_5();
							 | 
						||
| 
								 | 
							
								    test_unordered_6();
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    size_t value = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    std::vector<size_t> bandwidth_seconds{};
							 | 
						||
| 
								 | 
							
								    for(size_t iteration{0}; iteration < 600; iteration++) {
							 | 
						||
| 
								 | 
							
								        if(iteration >= 200 && iteration <= 270)
							 | 
						||
| 
								 | 
							
								            bandwidth_seconds.push_back(0);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            bandwidth_seconds.push_back(500);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    constexpr auto cofactor = 0.915;
							 | 
						||
| 
								 | 
							
								    //constexpr auto cofactor = 0.978;
							 | 
						||
| 
								 | 
							
								    for(size_t iteration{0}; iteration < bandwidth_seconds.size(); iteration++) {
							 | 
						||
| 
								 | 
							
								        const auto next_value = value * cofactor + bandwidth_seconds[iteration] * (1 - cofactor);
							 | 
						||
| 
								 | 
							
								        if(next_value > value)
							 | 
						||
| 
								 | 
							
								            value = ceil(next_value);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            value = floor(next_value);
							 | 
						||
| 
								 | 
							
								        std::cout << iteration << ": " << value << "\n";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |