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"; | ||
|  |     } | ||
|  | } |