restructure and add server/client example

This commit is contained in:
2025-01-24 10:34:04 +01:00
parent 729b475135
commit ec7b293bd5
30 changed files with 299 additions and 15 deletions

65
shared/src/values/Dna.cpp Normal file
View File

@@ -0,0 +1,65 @@
#include <cmath>
#include <cstddef>
#include "values/Dna.hpp"
namespace DNA
{
void newDna(Dna *dna, uint128 *state)
{
uint8_t *array = (uint8_t *)dna;
for (size_t i = 0; i < sizeof(Dna); i++)
{
array[i] = mrand::getValue(0, 255, state);
}
return;
}
void makeChild(Dna *p1, Dna *p2, Dna *c, uint128 *state)
{
uint8_t *p1a = (uint8_t *)p1;
uint8_t *p2a = (uint8_t *)p2;
uint8_t *ca = (uint8_t *)c;
for (size_t i = 0; i < sizeof(Dna); i++)
{
int val = mrand::getValue(0, 1, state);
if (val == 0)
{
ca[i] = p1a[i];
}
else
{
ca[i] = p2a[i];
}
}
}
void clone(Dna *p1, Dna *c, uint128 *state)
{
uint8_t *p1a = (uint8_t *)p1;
uint8_t *ca = (uint8_t *)c;
for (size_t i = 0; i < sizeof(Dna); i++)
{
int val = mrand::getValue(0, 1, state);
if (val == 0)
{
ca[i] = p1a[i];
}
else
{
ca[i] = mrand::getValue(0, 255, state);
}
}
}
void mutate(Dna *dna, uint32_t num, uint128 *state)
{
uint8_t *array = (uint8_t *)dna;
for (size_t i = 0; i < num; i++)
{
int pos = mrand::getValue(0, sizeof(Dna), state);
array[pos] = mrand::getValue(0, 255, state);
}
}
}

View File

@@ -0,0 +1,112 @@
#include <unistd.h>
#include "values/DnaManager.hpp"
UiUnit DnaManager::next(DnaManagerData *data)
{
if (data->queued >= NUM_PER_GEN)
{
return {nullptr, Liked::tbd, -1};
}
Dna *ret = &data->vector[data->queued];
int index = data->queued++;
return {ret, Liked::tbd, index};
}
bool DnaManager::like(UiUnit unit, DnaManagerData *data)
{
int found = -1;
if (unit.index == data->showed)
{
found = data->showed;
}
if (found == -1)
{
// RUN OUT OF GEN WAITING FOR NEW GEN
return false;
}
if (unit.liked == Liked::yes)
{
data->liked.push_back(found);
}
else if (unit.liked == Liked::no)
{
data->disliked.push_back(found);
}
else
{
// could be infinite loop if something went wrong and user lost UiUnit and next is returning null thinking that it queued everiting
// maybe return true to move on and maybe tread Liked::tbd as Liked::no
return false;
}
data->showed++;
if (data->showed >= NUM_PER_GEN && data->queued >= NUM_PER_GEN) // if buffer was biger in the past showed could be more then NUM_PER_GEN so its changed to >= insted of ==
{
return true;
}
return false;
}
void DnaManager::newGen(DnaManagerData *data)
{
data->queued = 0;
data->showed = 0;
data->generation += 1;
if (data->liked.size() == 0)
{
for (std::size_t i = 0; i < NUM_PER_GEN; i++)
{
DNA::newDna(&data->vector[i], &data->randSeed);
}
data->disliked.clear();
return;
}
if (data->liked.size() == 1)
{
int front = data->liked.front();
for (auto &&i : data->disliked)
{
DNA::clone(&data->vector[front], &data->vector[i], &data->randSeed);
}
data->disliked.clear();
data->liked.clear();
}
if (data->liked.size() >= 2)
{
for (auto &&i : data->disliked)
{
size_t p1 = mrand::getValue(0, data->liked.size() - 1, &data->randSeed);
size_t p2 = mrand::getValue(0, data->liked.size() - 1, &data->randSeed);
while (p1 == p2)
{
p2 = mrand::getValue(0, data->liked.size(), &data->randSeed);
}
p1 = data->liked[p1];
p2 = data->liked[p2];
Dna *p1p = &data->vector[p1];
Dna *p2p = &data->vector[p2];
Dna *c = &data->vector[i];
DNA::makeChild(p1p, p2p, c, &data->randSeed);
}
}
for (size_t i = 0; i < NUM_PER_GEN; i++)
{
DNA::mutate(&data->vector[i], NUM_OF_MUT, &data->randSeed);
}
data->disliked.clear();
data->liked.clear();
}

View File

@@ -0,0 +1,63 @@
#include <cinttypes>
#include <algorithm>
#include "values/mrand.hpp"
static inline uint32_t my_rotate_left(const uint32_t x, int k)
{
return (x << k) | (x >> (32 - k));
}
uint32_t my_rprand_xoshiro(uint32_t state[4])
{
const uint32_t result = my_rotate_left(state[1] * 5, 7) * 9;
const uint32_t t = state[1] << 9;
state[2] ^= state[0];
state[3] ^= state[1];
state[1] ^= state[2];
state[0] ^= state[3];
state[2] ^= t;
state[3] = my_rotate_left(state[3], 11);
return result;
}
uint64_t rprand_splitmix64(uint64_t &rprand_seed)
{
uint64_t z = (rprand_seed += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
namespace mrand
{
uint128 getState(unsigned long long seed)
{
uint64_t rprand_seed = (uint64_t)seed; // Set SplitMix64 seed for further use
uint128 rprand_state;
// To generate the Xoshiro128** state, we use SplitMix64 generator first
// We generate 4 pseudo-random 64bit numbers that we combine using their LSB|MSB
rprand_state.a = (uint32_t)(rprand_splitmix64(rprand_seed) & 0xffffffff);
rprand_state.b = (uint32_t)((rprand_splitmix64(rprand_seed) & 0xffffffff00000000) >> 32);
rprand_state.c = (uint32_t)(rprand_splitmix64(rprand_seed) & 0xffffffff);
rprand_state.d = (uint32_t)((rprand_splitmix64(rprand_seed) & 0xffffffff00000000) >> 32);
return rprand_state;
}
int getValue(int min, int max, uint128 *state)
{
int value = my_rprand_xoshiro((uint32_t *)state) % (std::abs(max - min) + 1) + min;
return value;
}
float getFloat(uint128 *state)
{
return my_rprand_xoshiro((uint32_t *)state) / 4294967295.0f;
}
}