MAJ pour upgrade pc backup
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
#include "Configuration.hpp"
|
||||
|
||||
namespace Setup {
|
||||
ServerConfiguration Configuration::serverConfig;
|
||||
|
||||
void Configuration::init(std::string configuration)
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CONFIGURATION_HPP
|
||||
#define CONFIGURATION_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Setup {
|
||||
|
||||
constexpr const char* getDefaultConfigurationPath() {return "configuration.json"; };
|
||||
|
||||
struct ServerConfiguration
|
||||
{
|
||||
unsigned int port = 5000;
|
||||
std::string url = "0.0.0.0";
|
||||
};
|
||||
|
||||
class Configuration
|
||||
{
|
||||
private:
|
||||
static ServerConfiguration serverConfig;
|
||||
public:
|
||||
Configuration() = delete;
|
||||
static const ServerConfiguration& server() {return serverConfig;};
|
||||
static void init(std::string configuration = getDefaultConfigurationPath());
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "HttpServer.hpp"
|
||||
#include "../Configuration/Configuration.hpp"
|
||||
|
||||
namespace WebAccess {
|
||||
|
||||
void HttpServer::initServer()
|
||||
{
|
||||
m_server.new_task_queue = [] {
|
||||
return new ThreadPool(1);
|
||||
};//LIMIT THE NUMBER OF SIMULTANEOUS RESOLUTION TO 1 => TO CHANGE IT, MAKE THE SIMULATION THREAD SAFE
|
||||
|
||||
m_server.Post("/simulate", [&](const Request &req, Response &res) {
|
||||
std::cout << "Request received trying to get instance and launch solver" << std::endl;
|
||||
std::string body = req.body;
|
||||
res.body = "OK";
|
||||
});
|
||||
m_server.Get("/ping", [&](const Request &req, Response &res) {
|
||||
std::string body = req.body;
|
||||
res.body = "OK";
|
||||
});
|
||||
}
|
||||
|
||||
void HttpServer::listen()
|
||||
{
|
||||
std::cout << "Listening to " << Setup::Configuration::server().url << ":"
|
||||
<< Setup::Configuration::server().port << std::endl;
|
||||
m_server.listen(Setup::Configuration::server().url.c_str(), (int) Setup::Configuration::server().port);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef HTTPSERVER_HPP
|
||||
#define HTTPSERVER_HPP
|
||||
|
||||
#include <httplib.h>
|
||||
|
||||
namespace WebAccess {
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
class HttpServer{
|
||||
|
||||
private:
|
||||
|
||||
Server m_server;
|
||||
|
||||
public:
|
||||
|
||||
HttpServer() = default;
|
||||
|
||||
void initServer();
|
||||
|
||||
void listen();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef CANDIDATE_HPP
|
||||
#define CANDIDATE_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
namespace Elections
|
||||
{
|
||||
|
||||
enum class Party
|
||||
{
|
||||
HORIZONS,
|
||||
LFI,
|
||||
RN,
|
||||
LR,
|
||||
PCF,
|
||||
ECOLO,
|
||||
PS,
|
||||
LO,
|
||||
NPA,
|
||||
RENAISSANCE,
|
||||
ANIMALISTE
|
||||
};
|
||||
|
||||
enum class Bord
|
||||
{
|
||||
EG,
|
||||
G,
|
||||
CG,
|
||||
EC,
|
||||
CD,
|
||||
D,
|
||||
ED
|
||||
};
|
||||
|
||||
|
||||
class Candidate
|
||||
{
|
||||
private:
|
||||
Bord bord;
|
||||
Party party;
|
||||
std::string name;
|
||||
public:
|
||||
struct hashCandidate
|
||||
{
|
||||
size_t operator()(const Candidate& cand) const
|
||||
{
|
||||
return std::hash<std::string>{}(cand.name);
|
||||
}
|
||||
};
|
||||
bool operator==(const Candidate& other) const
|
||||
{
|
||||
return name == other.name;
|
||||
}
|
||||
Candidate(std::string n, Bord b, Party p): bord(b), party(p), name(n){}
|
||||
|
||||
Bord getBord()const {return bord;}
|
||||
Party getParty() const {return party;}
|
||||
std::string getName() const {return name;}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef CATEGORY_HPP
|
||||
#define CATEGORY_HPP
|
||||
|
||||
#include "Criterion.hpp"
|
||||
#include "VoteScheme.hpp"
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace People {
|
||||
|
||||
template<typename T>
|
||||
concept CatEnum = std::is_enum_v<T> && (
|
||||
std::is_same_v<T, Region> ||
|
||||
std::is_same_v<T, TypeZone> ||
|
||||
std::is_same_v<T, TrancheAge> ||
|
||||
std::is_same_v<T, CategorieSocioPro> ||
|
||||
std::is_same_v<T, NiveauDiplome> ||
|
||||
std::is_same_v<T, Sexe>
|
||||
);
|
||||
|
||||
template<CatEnum... Crits>
|
||||
class Category
|
||||
{
|
||||
private:
|
||||
static_assert(sizeof...(Crits) > 0, "At least one criterion");
|
||||
std::tuple<Crits...> criteria;
|
||||
std::size_t pop;
|
||||
VoteScheme voteScheme;
|
||||
template<std::size_t I = 0, CatEnum C>
|
||||
bool hasCriterionImpl(C val) const
|
||||
{
|
||||
if constexpr (I < sizeof...(Crits))
|
||||
{
|
||||
using ElemType = std::tuple_element_t<I, std::tuple<Crits...>>;
|
||||
if constexpr (std::is_same_v<ElemType, C>)
|
||||
{
|
||||
if (std::get<I>(criteria) == val)
|
||||
return true;
|
||||
}
|
||||
return hasCriterionImpl<I + 1>(val);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
// Constructeur : reçoit les valeurs brutes des enums
|
||||
Category(Crits... values, size_t p): criteria(values...), pop(p){}
|
||||
|
||||
std::size_t getPop() const {return pop;}
|
||||
|
||||
template<CatEnum C>
|
||||
bool hasCriterion(C val) const
|
||||
{
|
||||
return hasCriterionImpl(val);
|
||||
}
|
||||
|
||||
VoteScheme& getVoteScheme() {return voteScheme;}
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef CRITERION_HPP
|
||||
#define CRITERION_HPP
|
||||
|
||||
namespace People {
|
||||
|
||||
enum class Region {
|
||||
// Grandes régions culturelles/politiques
|
||||
ILE_DE_FRANCE, // Métropole parisienne
|
||||
BASSIN_PARISIEN, // Picardie, Centre, Normandie
|
||||
GRAND_EST, // Alsace, Lorraine, Champagne
|
||||
HAUTS_DE_FRANCE, // Nord - ancien bassin minier
|
||||
NORMANDIE,
|
||||
BRETAGNE,
|
||||
PAYS_DE_LOIRE,
|
||||
CENTRE_VAL_LOIRE,
|
||||
NOUVELLE_AQUITAINE,
|
||||
OCCITANIE,
|
||||
PROVENCE_ALPES_COTE_AZUR,
|
||||
AUVERGNE_RHONE_ALPES,
|
||||
BOURGOGNE_FRANCHE_COMTE,
|
||||
CORSE,
|
||||
DOM_TOM
|
||||
};
|
||||
|
||||
// Ou version plus simple : typologie urbaine
|
||||
enum class TypeZone {
|
||||
METROPOLE_GRANDE, // Paris, Lyon, Marseille, Lille, Bordeaux
|
||||
METROPOLE_MOYENNE, // 100k-500k
|
||||
VILLE_MOYENNE, // 20k-100k
|
||||
VILLE_PETITE, // 2k-20k
|
||||
RURAL_PROFOND, // <2k
|
||||
PERIURBAIN, // Couronne des métropoles
|
||||
BANLIEUE_SENSIBLE // Quartiers politique de la ville + défavorisée
|
||||
};
|
||||
|
||||
|
||||
enum class TrancheAge
|
||||
{
|
||||
MOINS_15,
|
||||
_15_24,
|
||||
_25_39,
|
||||
_40_54,
|
||||
_55_64,
|
||||
_65_79,
|
||||
_80_PLUS
|
||||
};
|
||||
|
||||
//Population
|
||||
enum class CategorieSocioPro
|
||||
{
|
||||
Agriculteurs,
|
||||
ArtisansCommerçants,
|
||||
CadresCadresSup,
|
||||
ProfessionsIntermediaires,
|
||||
EmployesQualifies,
|
||||
EmployesNonQualifies,
|
||||
OuvriersQualifies,
|
||||
OuvriersNonQualifies,
|
||||
JamaisTravaille
|
||||
};
|
||||
|
||||
enum class NiveauDiplome
|
||||
{
|
||||
AUCUN,
|
||||
BREVET,
|
||||
BAC,
|
||||
BACPLUS
|
||||
};
|
||||
|
||||
enum class Sexe
|
||||
{
|
||||
HOMME,
|
||||
FEMME
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef POPULATION_HPP
|
||||
#define POPULATION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include "Category.hpp"
|
||||
|
||||
namespace People {
|
||||
|
||||
constexpr size_t VotantsInscrits = 49339714;
|
||||
|
||||
template<CatEnum... CritsT>
|
||||
class Citizens
|
||||
{
|
||||
private:
|
||||
using CategoryType = Category<CritsT...>;
|
||||
std::vector<CategoryType> categories;
|
||||
|
||||
public:
|
||||
|
||||
template<CatEnum... critToCheck>
|
||||
std::vector<CategoryType> getPopulation(critToCheck... criteria) const
|
||||
{
|
||||
std::vector<CategoryType> res;
|
||||
for (const CategoryType& cat : categories)
|
||||
{
|
||||
if ((cat.hasCriterion(criteria) && ...))
|
||||
res.push_back(cat);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void addCategory(CritsT... criteres, size_t pop){
|
||||
categories.emplace_back(criteres..., pop);
|
||||
};
|
||||
|
||||
auto begin(){return categories.begin();}
|
||||
auto end(){return categories.end();}
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef RANDOM_HPP
|
||||
#define RANDOM_HPP
|
||||
|
||||
#include <random>
|
||||
namespace Random{
|
||||
inline std::mt19937 makeRandom(){
|
||||
return std::mt19937(std::random_device{}());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef RESULT_HPP
|
||||
#define RESULT_HPP
|
||||
|
||||
#include "Candidate.hpp"
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
namespace Elections {
|
||||
|
||||
class Result
|
||||
{
|
||||
private:
|
||||
std::unordered_map<Elections::Candidate, size_t, Elections::Candidate::hashCandidate> votesPerCandidate;
|
||||
public:
|
||||
Result() = default;
|
||||
void addVote(Candidate candidate){votesPerCandidate[candidate]++;}
|
||||
void print()
|
||||
{
|
||||
std::map<size_t, Candidate, std::greater<size_t>> resOrder;
|
||||
for(auto& [key, val]: votesPerCandidate)
|
||||
{
|
||||
resOrder.insert({val, key});
|
||||
}
|
||||
for(auto& [key, val] : resOrder)
|
||||
{
|
||||
std::cout << val.getName() << " nb Voix : " << key << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "Simulator.hpp"
|
||||
#include "Candidate.hpp"
|
||||
#include "Criterion.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
namespace Elections {
|
||||
|
||||
void Simulator::reportVotesToSecondRound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Simulator::simulate(){
|
||||
for(auto& pop : people)
|
||||
{
|
||||
for(size_t person = 0; person < pop.getPop(); ++person)
|
||||
{
|
||||
roundsResults[0].addVote(pop.getVoteScheme().vote(rng));
|
||||
}
|
||||
}
|
||||
reportVotesToSecondRound();
|
||||
}
|
||||
|
||||
void Simulator::initializePopulation(){
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::CadresCadresSup, 98413);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::CadresCadresSup, 224778);
|
||||
|
||||
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::JamaisTravaille, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::Agriculteurs, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::ArtisansCommerçants, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::EmployesNonQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::EmployesQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::OuvriersNonQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::OuvriersQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::FEMME, People::CategorieSocioPro::ProfessionsIntermediaires, 20000000);
|
||||
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::JamaisTravaille, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::Agriculteurs, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::ArtisansCommerçants, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::EmployesNonQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::EmployesQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::OuvriersNonQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::OuvriersQualifies, 20000000);
|
||||
people.addCategory(People::TrancheAge::_15_24, People::Sexe::HOMME, People::CategorieSocioPro::ProfessionsIntermediaires, 20000000);
|
||||
|
||||
}
|
||||
|
||||
void Simulator::initializeCandidates()
|
||||
{
|
||||
candidates.emplace_back(Candidate("JLM", Bord::G, Party::LFI));
|
||||
candidates.emplace_back(Candidate("MERDELLA", Bord::ED, Party::RN));
|
||||
}
|
||||
|
||||
void Simulator::initializeProbabilites()
|
||||
{
|
||||
for(auto& pop: people)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Simulator::init()
|
||||
{
|
||||
initializeCandidates();
|
||||
initializePopulation();
|
||||
initializeProbabilites();
|
||||
}
|
||||
|
||||
void Simulator::results()
|
||||
{
|
||||
for(auto& res : roundsResults)
|
||||
{
|
||||
res.print();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef SIMULATOR_HPP
|
||||
#define SIMULATOR_HPP
|
||||
|
||||
#include <array>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include "Candidate.hpp"
|
||||
#include "People.hpp"
|
||||
#include "Result.hpp"
|
||||
#include "Random.hpp"
|
||||
|
||||
namespace Elections {
|
||||
class Simulator
|
||||
{
|
||||
private:
|
||||
std::array<Result, 2> roundsResults;
|
||||
std::mt19937 rng;
|
||||
People::Citizens<People::TrancheAge, People::Sexe, People::CategorieSocioPro> people;
|
||||
std::vector<Candidate> candidates;
|
||||
void reportVotesToSecondRound();
|
||||
void initializePopulation();
|
||||
void initializeCandidates();
|
||||
void initializeProbabilites();
|
||||
public:
|
||||
Simulator(){ rng = Random::makeRandom();};
|
||||
void simulate();
|
||||
void init();
|
||||
void results();
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef VOTESCHEME_HPP
|
||||
#define VOTESCHEME_HPP
|
||||
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "Candidate.hpp"
|
||||
#include "Random.hpp"
|
||||
namespace People {
|
||||
|
||||
class VoteScheme{
|
||||
private:
|
||||
std::unordered_map<Elections::Candidate, double, Elections::Candidate::hashCandidate> probPerCandidate;
|
||||
public:
|
||||
VoteScheme() = default;
|
||||
void setProp(Elections::Candidate& cand, double prop)
|
||||
{
|
||||
probPerCandidate[cand] = prop;
|
||||
}
|
||||
|
||||
Elections::Candidate vote(std::mt19937& rng) const
|
||||
{
|
||||
std::vector<Elections::Candidate> candOrder;
|
||||
std::vector<double> cumul;
|
||||
|
||||
double sum = 0.0;
|
||||
for (auto& [cand, prob] : probPerCandidate)
|
||||
{
|
||||
candOrder.push_back(cand);
|
||||
sum += prob;
|
||||
cumul.push_back(sum);
|
||||
}
|
||||
|
||||
double roll = std::uniform_real_distribution<double>(0.0, 1.0)(rng);
|
||||
|
||||
for (size_t i = 0; i < candOrder.size(); ++i)
|
||||
{
|
||||
if (roll <= cumul[i])
|
||||
return candOrder[i];
|
||||
}
|
||||
|
||||
return candOrder.back();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+26
-386
@@ -1,392 +1,32 @@
|
||||
#include "Server/HttpServer.hpp"
|
||||
#include "Simulator/Simulator.hpp"
|
||||
#include "iostream"
|
||||
#include "array"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
constexpr size_t VotantsInscrits = 49339714;
|
||||
std::mt19937 rng(std::random_device{}());
|
||||
|
||||
// Nouveau : Géographie
|
||||
/*enum class Region {
|
||||
// Grandes régions culturelles/politiques
|
||||
ILE_DE_FRANCE, // Métropole parisienne
|
||||
BASSIN_PARISIEN, // Picardie, Centre, Normandie
|
||||
GRAND_EST, // Alsace, Lorraine, Champagne
|
||||
HAUTS_DE_FRANCE, // Nord - ancien bassin minier
|
||||
NORMANDIE,
|
||||
BRETAGNE,
|
||||
PAYS_DE_LOIRE,
|
||||
CENTRE_VAL_LOIRE,
|
||||
NOUVELLE_AQUITAINE,
|
||||
OCCITANIE,
|
||||
PROVENCE_ALPES_COTE_AZUR,
|
||||
AUVERGNE_RHONE_ALPES,
|
||||
BOURGOGNE_FRANCHE_COMTE,
|
||||
CORSE,
|
||||
DOM_TOM
|
||||
};*/
|
||||
|
||||
// Ou version plus simple : typologie urbaine
|
||||
enum class TypeZone {
|
||||
METROPOLE_GRANDE, // Paris, Lyon, Marseille, Lille, Bordeaux
|
||||
METROPOLE_MOYENNE, // 100k-500k
|
||||
VILLE_MOYENNE, // 20k-100k
|
||||
VILLE_PETITE, // 2k-20k
|
||||
RURAL_PROFOND, // <2k
|
||||
PERIURBAIN, // Couronne des métropoles
|
||||
BANLIEUE_SENSIBLE // Quartiers politique de la ville + défavorisée
|
||||
};
|
||||
|
||||
|
||||
//Candidat
|
||||
enum class Bord
|
||||
{
|
||||
EXTREME_GAUCHE,
|
||||
GAUCHE,
|
||||
CENTRE_GAUCHE,
|
||||
CENTRE_DROIT,
|
||||
DROITE,
|
||||
EXTREME_DROITE
|
||||
};
|
||||
|
||||
struct Candidat
|
||||
{
|
||||
std::string name;
|
||||
Bord bord;
|
||||
|
||||
double position_economique; // -1 = collectivisme, +1 = libéralisme
|
||||
double position_societale; // -1 = progressiste, +1 = conservateur
|
||||
double position_europe; // -1 = fédéraliste, +1 = eurosceptique
|
||||
};
|
||||
|
||||
enum class TrancheAge
|
||||
{
|
||||
MOINS_25, // 18-24 ans
|
||||
_25_34, // 25-34 ans
|
||||
_35_49, // 35-49 ans
|
||||
_50_64, // 50-64 ans
|
||||
_65_79, // 65-79 ans
|
||||
_80_PLUS // 80 ans et plus
|
||||
};
|
||||
|
||||
//Population
|
||||
enum class CategorieSocioPro
|
||||
{
|
||||
Agriculteurs,
|
||||
ArtisansCommerçants,
|
||||
CadresCadresSup,
|
||||
ProfessionsIntermediaires,
|
||||
EmployesQualifies,
|
||||
EmployesNonQualifies,
|
||||
OuvriersQualifies,
|
||||
OuvriersNonQualifies,
|
||||
JamaisTravaille
|
||||
};
|
||||
|
||||
enum class NiveauDiplome
|
||||
{
|
||||
AUCUN,
|
||||
BREVET,
|
||||
BAC,
|
||||
BACPLUS
|
||||
};
|
||||
|
||||
// Structure pour une strate de population
|
||||
struct Strate {
|
||||
CategorieSocioPro csp;
|
||||
TrancheAge age;
|
||||
NiveauDiplome diplome;
|
||||
TypeZone zone;
|
||||
//Region region;
|
||||
double population; // nombre d'individus
|
||||
double probabiliteParticipation;
|
||||
|
||||
// Position politique moyenne de la strate
|
||||
double position_economique;
|
||||
double position_societale;
|
||||
double position_europe;
|
||||
};
|
||||
|
||||
struct Result {
|
||||
std::unordered_map<std::string, unsigned int> countVotePerCand;
|
||||
unsigned int totalVotes = 0;
|
||||
unsigned int totalAbs = 0;
|
||||
};
|
||||
|
||||
std::vector<Candidat> candidats;
|
||||
std::vector<Strate> strates;
|
||||
|
||||
|
||||
// Calcule la distance politique entre un électeur (strate) et un candidat
|
||||
double distancePolitique(const Strate& strate, const Candidat& candidat) {
|
||||
double diff_economic = strate.position_economique - candidat.position_economique;
|
||||
double diff_societal = strate.position_societale - candidat.position_societale;
|
||||
double diff_europe = strate.position_europe - candidat.position_europe;
|
||||
|
||||
// Pondération : le sociétal et l'europe sont plus clivants qu'avant
|
||||
return std::sqrt(
|
||||
0.4 * diff_economic * diff_economic +
|
||||
0.4 * diff_societal * diff_societal +
|
||||
0.1 * diff_europe * diff_europe
|
||||
);
|
||||
}
|
||||
|
||||
// Détermine la position politique d'une strate selon ses caractéristiques
|
||||
void calculerPositionStrate(Strate& strate) {
|
||||
double eco = 0.0, soc = 0.0, eu = 0.0;
|
||||
|
||||
// Effet CSP
|
||||
switch(strate.csp) {
|
||||
case CategorieSocioPro::Agriculteurs:
|
||||
eco = -0.2; soc = 0.5; eu = 0.6; break;
|
||||
case CategorieSocioPro::OuvriersNonQualifies:
|
||||
eco = -0.4; soc = 0.4; eu = 0.5; break;
|
||||
case CategorieSocioPro::CadresCadresSup:
|
||||
eco = 0.4; soc = -0.3; eu = -0.1; break;
|
||||
case CategorieSocioPro::EmployesQualifies:
|
||||
eco = 0.0; soc = 0.1; eu = 0.2; break;
|
||||
default:
|
||||
eco = 0.0; soc = 0.0; eu = 0.0;
|
||||
}
|
||||
|
||||
// Effet âge
|
||||
switch(strate.age) {
|
||||
case TrancheAge::MOINS_25:
|
||||
soc -= 0.3; eco -= 0.2; eu -= 0.2; break;
|
||||
case TrancheAge::_65_79:
|
||||
soc += 0.2; break;
|
||||
case TrancheAge::_80_PLUS:
|
||||
soc += 0.3; eco += 0.1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Effet diplôme
|
||||
switch(strate.diplome) {
|
||||
case NiveauDiplome::BACPLUS:
|
||||
eco += 0.2; soc -= 0.2; eu -= 0.2; break;
|
||||
case NiveauDiplome::AUCUN:
|
||||
eco -= 0.1; soc += 0.3; eu += 0.3; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Effet géographique
|
||||
switch(strate.zone) {
|
||||
case TypeZone::METROPOLE_GRANDE:
|
||||
eco += 0.3; soc -= 0.2; eu -= 0.1; break;
|
||||
case TypeZone::RURAL_PROFOND:
|
||||
eco -= 0.2; soc += 0.4; eu += 0.3; break;
|
||||
case TypeZone::BANLIEUE_SENSIBLE:
|
||||
eco -= 0.3; soc += 0.1; eu -= 0.1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch(strate.region) {
|
||||
case Region::PROVENCE_ALPES_COTE_AZUR:
|
||||
soc += 0.2; eu += 0.2; break;
|
||||
case Region::ILE_DE_FRANCE:
|
||||
eco += 0.2; soc -= 0.1; eu += 0.1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Clamping entre -1 et 1
|
||||
strate.position_economique = std::max(-1.0, std::min(1.0, eco));
|
||||
strate.position_societale = std::max(-1.0, std::min(1.0, soc));
|
||||
strate.position_europe = std::max(-1.0, std::min(1.0, eu));
|
||||
}
|
||||
|
||||
// Vote avec un modèle probabiliste
|
||||
std::string voter(const Strate& strate, std::mt19937& gen) {
|
||||
// Calcule les distances à tous les candidats
|
||||
std::vector<std::pair<std::string, double>> scores;
|
||||
|
||||
for (const auto& candidat : candidats) {
|
||||
double distance = distancePolitique(strate, candidat);
|
||||
// La probabilité est inversement proportionnelle à la distance
|
||||
// avec un facteur de bruit (température)
|
||||
double temperature = 0.05; // Plus c'est grand, plus le vote est aléatoire
|
||||
double score = std::exp(-distance / temperature);
|
||||
scores.push_back({candidat.name, score});
|
||||
}
|
||||
|
||||
// Tirage aléatoire pondéré par les scores
|
||||
std::uniform_real_distribution<> dis(0, 1);
|
||||
double r = dis(gen);
|
||||
double cumul = 0.0;
|
||||
|
||||
for (const auto& [nom, score] : scores) {
|
||||
cumul += score;
|
||||
if (r < cumul) return nom;
|
||||
}
|
||||
|
||||
return scores.back().first;
|
||||
}
|
||||
|
||||
void initStrates()
|
||||
{
|
||||
struct sousStrate{
|
||||
TypeZone zone;
|
||||
TrancheAge age;
|
||||
CategorieSocioPro csp;
|
||||
double pop;
|
||||
};
|
||||
|
||||
std::vector<std::tuple<CategorieSocioPro, TrancheAge, NiveauDiplome, TypeZone, double>> rawData = {
|
||||
// Format : CSP, Age, Diplome, Zone, Region, population (en millions)
|
||||
|
||||
//Ile de france
|
||||
{CategorieSocioPro::CadresCadresSup, TrancheAge::MOINS_25, NiveauDiplome::BACPLUS,
|
||||
TypeZone::METROPOLE_GRANDE, 2.3},
|
||||
|
||||
{CategorieSocioPro::CadresCadresSup, TrancheAge::MOINS_25, NiveauDiplome::BACPLUS,
|
||||
TypeZone::METROPOLE_GRANDE, 2.3},
|
||||
|
||||
|
||||
{CategorieSocioPro::CadresCadresSup, TrancheAge::MOINS_25, NiveauDiplome::BACPLUS,
|
||||
TypeZone::METROPOLE_GRANDE, 2.3},
|
||||
|
||||
};
|
||||
|
||||
double total = 0;
|
||||
for (const auto& [csp, age, diplome, zone, pop] : rawData) {
|
||||
Strate s;
|
||||
s.csp = csp;
|
||||
s.age = age;
|
||||
s.diplome = diplome;
|
||||
s.zone = zone;
|
||||
//s.region = region;
|
||||
s.population = pop * 1e6; // Convertir en individus
|
||||
total += s.population;
|
||||
|
||||
// Taux de participation selon âge et CSP
|
||||
switch (age) {
|
||||
|
||||
case TrancheAge::MOINS_25: s.probabiliteParticipation = 0.58;
|
||||
case TrancheAge::_25_34: s.probabiliteParticipation = 0.54;
|
||||
case TrancheAge::_35_49: s.probabiliteParticipation = 0.78;
|
||||
case TrancheAge::_50_64: s.probabiliteParticipation = 0.84;
|
||||
case TrancheAge::_65_79: s.probabiliteParticipation = 0.88;
|
||||
case TrancheAge::_80_PLUS: s.probabiliteParticipation = 0.77;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
calculerPositionStrate(s);
|
||||
strates.push_back(s);
|
||||
}
|
||||
|
||||
// Normaliser pour atteindre exactement VotantsInscrits
|
||||
double facteur = (double)VotantsInscrits / total;
|
||||
for (auto& s : strates) {
|
||||
s.population *= facteur;
|
||||
}
|
||||
}
|
||||
|
||||
void simulateElection()
|
||||
{
|
||||
Result result;
|
||||
|
||||
// Initialiser les compteurs pour chaque candidat
|
||||
for (const auto& c : candidats) {
|
||||
result.countVotePerCand[c.name] = 0;
|
||||
}
|
||||
|
||||
std::cout << "=== SIMULATION ÉLECTION PRÉSIDENTIELLE ===\n";
|
||||
std::cout << "Population totale: " << VotantsInscrits << " inscrits\n\n";
|
||||
|
||||
int total_votants_simules = 0;
|
||||
|
||||
// Pour chaque strate
|
||||
for (const auto& strate : strates) {
|
||||
// Nombre de votants dans cette strate (binomial)
|
||||
std::binomial_distribution<int> dist_votants(strate.population,
|
||||
strate.probabiliteParticipation);
|
||||
int votants = dist_votants(rng);
|
||||
int abstention = (int)strate.population - votants;
|
||||
|
||||
result.totalAbs += abstention;
|
||||
|
||||
// Faire voter chaque électeur
|
||||
for (int i = 0; i < votants; ++i) {
|
||||
std::string vote = voter(strate, rng);
|
||||
result.countVotePerCand[vote]++;
|
||||
result.totalVotes++;
|
||||
}
|
||||
|
||||
// Debug : affichage par strate
|
||||
std::cout << "Strate: " << (int)strate.csp << "/" << (int)strate.age
|
||||
<< " - Pop: " << (int)strate.population
|
||||
<< " - Votants: " << votants << "\n";
|
||||
}
|
||||
|
||||
// Affichage des résultats
|
||||
std::cout << "\n=== RÉSULTATS ===\n";
|
||||
std::cout << "Total votants: " << result.totalVotes << "\n";
|
||||
std::cout << "Total abstentions: " << result.totalAbs << "\n";
|
||||
std::cout << "Taux participation: "
|
||||
<< (100.0 * result.totalVotes / VotantsInscrits) << "%\n\n";
|
||||
|
||||
// Trier les candidats par nombre de voix
|
||||
std::vector<std::pair<std::string, unsigned int>> sorted;
|
||||
for (const auto& [nom, voix] : result.countVotePerCand) {
|
||||
sorted.push_back({nom, voix});
|
||||
}
|
||||
std::sort(sorted.begin(), sorted.end(),
|
||||
[](auto& a, auto& b) { return a.second > b.second; });
|
||||
|
||||
std::cout << "Scores du premier tour:\n";
|
||||
for (const auto& [nom, voix] : sorted) {
|
||||
double pct = 100.0 * voix / result.totalVotes;
|
||||
std::cout << " " << nom << ": " << voix << " voix (" << pct << "%)\n";
|
||||
}
|
||||
|
||||
// Simulation second tour (top 2)
|
||||
std::string qualif1 = sorted[0].first;
|
||||
std::string qualif2 = sorted[1].first;
|
||||
|
||||
std::cout << "\n=== SECOND TOUR ===\n";
|
||||
std::cout << qualif1 << " vs " << qualif2 << "\n\n";
|
||||
|
||||
// Re-simuler le second tour avec reports de voix
|
||||
//simulerSecondTour(qualif1, qualif2, result);
|
||||
}
|
||||
|
||||
void initCandidats()
|
||||
{
|
||||
candidats = {
|
||||
// Extrême gauche
|
||||
{"L'Arthaud", Bord::EXTREME_GAUCHE, -0.8, -0.7, -0.3},
|
||||
{"Poutou", Bord::EXTREME_GAUCHE, -0.9, -0.6, -0.4},
|
||||
|
||||
// Gauche
|
||||
{"Mélenchon", Bord::GAUCHE, -0.6, -0.4, -0.2},
|
||||
{"Ruffin", Bord::GAUCHE, -0.5, -0.3, -0.1},
|
||||
|
||||
// Centre gauche
|
||||
{"Glucksmann", Bord::CENTRE_GAUCHE, -0.2, -0.3, 0.1},
|
||||
{"Rousseau", Bord::CENTRE_GAUCHE, -0.1, -0.2, 0.0},
|
||||
|
||||
// Centre droit
|
||||
{"Macron", Bord::CENTRE_DROIT, 0.3, 0.0, 0.4},
|
||||
{"Philippe", Bord::CENTRE_DROIT, 0.2, 0.1, 0.3},
|
||||
|
||||
// Droite
|
||||
{"Wauquiez", Bord::DROITE, 0.4, 0.5, 0.2},
|
||||
{"Bertrand", Bord::DROITE, 0.3, 0.4, 0.1},
|
||||
|
||||
// Extrême droite
|
||||
{"Le Pen", Bord::EXTREME_DROITE, 0.2, 0.7, 0.8},
|
||||
{"Zemmour", Bord::EXTREME_DROITE, 0.5, 0.9, 0.9}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#include <asm-generic/sockios.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
initCandidats();
|
||||
initStrates();
|
||||
simulateElection();
|
||||
if(argc == 1)
|
||||
{
|
||||
std::cout << "Usage : " << std::endl << "--server" << std::endl << "--simulate" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if(argc > 1)
|
||||
{
|
||||
std::string mode = argv[1];
|
||||
if(mode == "--server")
|
||||
{
|
||||
WebAccess::HttpServer server;
|
||||
server.initServer();
|
||||
server.listen();
|
||||
}
|
||||
else if (mode == "--simulate") {
|
||||
//todo
|
||||
Elections::Simulator simulation;
|
||||
simulation.init();
|
||||
simulation.simulate();
|
||||
simulation.results();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user