Взял и от нечего делать разобрал файлик с выгрузкой данных по электронному голосованию:
http://observer2020.mos.ru/observer/downloads/ballots_decrypted_2020-07-01T19:47:00.csv
Получился такой вот забавный график (кликабельно):
Интересно было бы сопоставить явно видимые на графике «скачки» с разными событиями прошедшей недели — например, резкий прирост голосов «за» в Москве в 17:00 25 июня, или синхронные скачки «против» в Москве и Нижнем в 16:00 26 июня и в 14:00 29 июня.
Наговняканный за полчаса код прилагается:
#include <stdio.h> #include <string.h> #include <stdlib.h> struct voteblock { int time; // time in seconds since day start int res[2][2]; }; voteblock votes[2300000]; // max. block number is about 2.27M int gettime(char *token){ token[2] = '\0'; token[5] = '\0'; int hours = atoi(token); int minutes = atoi(token + 3); int seconds = atoi(token + 6); return hours * 60 * 60 + minutes * 60 + seconds; } void process_vote(char *buf){ char *token; int district, res; token = strtok(buf, "\";"); // номер голоса int n = atoi(token); token = strtok(NULL, "\";"); // избир. округ if (strcmp(token, "77") == 0){ district = 0; } else if (strcmp(token, "52") == 0) { district = 1; } else { fprintf(stderr, "Unknown district %s\r\n", token); return; } strtok(NULL, "\";"); // адрес голоса в блокчейне token = strtok(NULL, "\";#"); // блок голоса int block = atoi(token); token = strtok(NULL, "\";"); // время записи блока голоса int time = gettime(token); strtok(NULL, ";"); // зашифрованный голос token = strtok(NULL, "\";"); // расшифрованный голос if (strcmp(token, "2212294583") == 0){ res = 0; } else if (strcmp(token, "450215437") == 0) { res = 1; } else { fprintf(stderr, "Unknown vote result %s\r\n", token); return; } strtok(NULL, "\";"); // блок расшифровки strtok(NULL, "\";"); // время записи блока расшифровки strtok(NULL, "\";"); // транзакция votes[block].time = time; votes[block].res[district][res]++; } void print_votes_table(){ int day = 0; int starttime = 7 * 3600; // 10:00:00 MSK = 7:00:00 UTC int delta = 10 * 60; // 10 minutes granularity int allvotes[2][2] = { 0 }; // to put the last line votes[sizeof(votes) / sizeof(voteblock) - 1].time = INT_MAX; for (int i = 0; i < sizeof(votes) / sizeof(voteblock); i++){ if (votes[i].time >= 0){ if ((votes[i].time > starttime + delta) || (votes[i].time < starttime)) { /* either end of current stats block or end of day*/ if (votes[i].time < starttime) { starttime = 0; day++; } else { starttime += delta; } // finalize this line printf("%i\t%i\t%i\t%i\t%i\t%i\r\n", day, starttime, allvotes[0][0], allvotes[0][1], allvotes[1][0], allvotes[1][1]); } allvotes[0][0] += votes[i].res[0][0]; allvotes[0][1] += votes[i].res[0][1]; allvotes[1][0] += votes[i].res[1][0]; allvotes[1][1] += votes[i].res[1][1]; } } } int main(void){ char buf[1024]; // should be enough fgets(buf, sizeof(buf), stdin); // skip first line while (!feof(stdin)){ fgets(buf, sizeof(buf), stdin); process_vote(buf); } print_votes_table(); return 0; }