<?
function simulate($regionId) {
    global $bdd;
    
    $set = 0;
    $req = $bdd->prepare('SELECT id FROM cSets WHERE region = ?');
    $req->execute(array($regionId));
    if ($data = $req->fetch()) {
        $set = $data["id"];
    }
    
    if ($set == 0) {
        return simulateRegionUntilConstruction($regionId, time());
    }
    else {
        $now = time();
        
        $regions = [];
        
        $req = $bdd->prepare('SELECT cSets.region FROM cSets WHERE cSets.id = ?');
        $req->execute(array($set));
        while ($data = $req->fetch()) {
            $regions[] = $data['region'];
        }
        
        do {
            $transport = true;
            
            $req = $bdd->prepare('SELECT MIN(cTransports.timeArrived) AS T FROM cSets JOIN cTransports ON cTransports.regionStart = cSets.region WHERE cSets.id = ?');
            $req->execute(array($set));
            $data = $req->fetch();
            
            $t = nullIsZero($data['T']);
            
            if ($t == 0 || $t > $now) {
                $t = $now;
                $transport = false;
            }
            
            foreach($regions as $region) {
                $tmp = simulateRegionUntilConstruction($region, $t);
                
                if ($region == $regionId) {
                    $result = $tmp;
                }
            }
            
            if ($transport) {
                $req = $bdd->prepare('SELECT * FROM cTransports WHERE cTransports.timeArrived = ?');
                $req->execute(array($t));
                while ($data = $req->fetch()) {
                    if (in_array($data['regionStart'], $regions)) { // not transports for other sets
                        
                        if ($data['way'] == 0) { // debut du retour
                            addResourcesInRegion($data['regionEnd'], $data['resource'], $data['amount']);
                            
                            $req2 = $bdd->prepare('UPDATE cTransports SET timeArrived = ?, way = ? WHERE id = ?');
                            $req2->execute(array($data['timeArrived'] + $data['time'], 1, $data['id']));
                        }
                        else { // debut de l'aller
                            $landPath = getPath($data['regionStart'], $data['regionEnd'], true, true);
                            $seaPath = getPath($data['regionStart'], $data['regionEnd'], false, true);
                            
                            if ($landPath['possible'] && (!$seaPath['possible'] || $landPath['time'] < $seaPath['time'])) {
                                $path = $landPath;
                            }
                            else {
                                $path = $seaPath;
                            }
                        
                            if (!$path["possible"] || resourcesInRegion($data['regionStart'], $data['resource']) < $data['amount']) { // if not enough resources
                                breakTrade($data['id']);
                            }
                            else {
                                addFundsFromRegion($data['regionStart'], $data['cost']);
                                removeFundsFromRegion($data['regionEnd'], $data['cost']);
                                
                                foreach ($path["userTaxes"] as $user => $taxes) { //TODO : OPTI
                                    addFunds($user, $taxes);
                                    removeFundsFromRegion($data['regionEnd'], $taxes);
                                }
                                
                                removeResourcesInRegion($data['regionStart'], $data['resource'], $data['amount']);
                            
                                $req2 = $bdd->prepare('UPDATE cTransports SET timeArrived = ?, way = ? WHERE id = ?');
                                $req2->execute(array($data['timeArrived'] + $data['time'], 0, $data['id']));
                            }
                        }
                    }
                }
            }
            
        } while ($t < $now);
        
        return $result;
    }
}

function simulateRegionUntilConstruction($regionId, $until) {
    global $bdd;

    $buildings = getBuildingsList();
    $techs = getTechsList();

    do {
        $constructionOrResearch = true;

        $req = $bdd->prepare('SELECT MIN(cBuildingConstructions.timeFinished) AS T FROM cBuildingConstructions WHERE territory >= ? AND territory <= ? ');
        $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId)));
        $data = $req->fetch();

        $tConstruction = nullIsZero($data['T']);
        
        $req = $bdd->prepare('SELECT MIN(cResearch.timeFinished) AS T FROM cResearch WHERE territory >= ? AND territory <= ? AND tech > 0');
        $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId)));
        $data = $req->fetch();

        $tResearch = nullIsZero($data['T']);
        
        if ($tConstruction == 0 && $tResearch == 0) {
            $t = 0;
        }
        else if ($tConstruction == 0) {
            $t = $tResearch;
        }
        else if ($tResearch == 0) {
            $t = $tConstruction;
        }
        else {
            $t = min($tConstruction, $tResearch);
        }

        if ($t == 0 || $t > $until) {
            $t = $until;
            $constructionOrResearch = false;
        }

        $result = simulateRegion($regionId, $t);

        if ($constructionOrResearch) {
            //Construction
            $req = $bdd->prepare('SELECT * FROM cBuildingConstructions WHERE territory >= ? AND territory <= ? AND timeFinished = ?');
            $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId), $t));
            
            while ($data = $req->fetch()) {
                
                $production = 0;
                
                if (array_key_exists("production", $buildings[$data['type']])) { //mine or plant
                    foreach ($buildings[$data['type']]["production"] as $key => $prod) {
                        $production = getResourceId($key);
                    }
                }
                else if (array_key_exists("techPower", $buildings[$data['type']])) { //lab
                    $req2 = $bdd->prepare('INSERT INTO cResearch (territory, tech, progress, timeBegun, timeFinished) VALUES(?, ?, ?, ?, ?)');
                    $req2->execute(array($data['territory'], 0, 0, 0, 0));
                } 
                
                $req2 = $bdd->prepare('INSERT INTO cBuildings (territory, type, production) VALUES(?, ?, ?)');
                $req2->execute(array($data['territory'], $data['type'], $production));
                
                $req2 = $bdd->prepare('DELETE FROM cBuildingConstructions WHERE territory = ?');
                $req2->execute(array($data['territory']));
            }
        }

        //Research (need to check as timeFinished can change)
        $req = $bdd->prepare('SELECT * FROM cResearch WHERE territory >= ? AND territory <= ? AND timeFinished = ? AND tech > 0');
        $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId), $t));
        
        while ($data = $req->fetch()) {
            $req2 = $bdd->prepare('INSERT INTO cTechs (user, tech) VALUES(?, ?)');
            $req2->execute(array(getRegionOwner($regionId), $data['tech']));
            
            $type = $techs[$data['tech']]['type'] . "Xp";
            
            $xps = [];
            
            foreach($data as $key => $val) {
                if (substr($key, -strlen("Xp")) === "Xp") {
                    $xps[] = $val;
                }
            }
            
            $req2 = $bdd->prepare('UPDATE cResearch SET tech = 0, timeFinished = 0, ' . $type . ' = ? WHERE territory = ?');
            $req2->execute(array($data[$type] + getXpGain($techs[$data['tech']]['xp'], $xps), $data['territory']));
        }
        
    } while ($t < $until);

    return $result;
}

function simulateRegion($regionId, $until) {
    global $bdd;
    
    $regionInfo = [
        "current" => [],
        "gained" => [],
        "fundsGained" => 0,
        "populationConsumption" => [],
        "owner" => 0,
        "currentInfluences" => [],
        "gainedInfluences" => [],
        "buildingInfluences" => [],
        "agricultureEfficiency" => [],
        "mineralEfficiency" => [],
        "buildingsProductionAmount" => [],
        "buildingsProductionResource" => [],
        "buildingsEfficiency" => [],
        "buildingsResourcesNeeded" => [],
        "buildingsHappiness" => [],
        "buildingsAdjacentHappiness" => [],
        "buildingsPopulation" => [],
        "buildingsMaintenance" => [],
        "buildingsTech" => [],
        "buildingsTechProgressPerSec" => [],
        "buildingsTechProgress" => [],
        "buildingsTechTimeBegun" => [],
        "buildingsTechTimeFinished" => [],
        "happiness" => 0,
        "happinessGrowth" => 0,
        "happinessBonus" => 0,
        "population" => 0,
        "populationGrowth" => 0
    ];
    
    $req = $bdd->prepare('SELECT cRegions.time AS TIME, cRegions.owner AS OWNER, cRegions.happiness AS HAP, cRegions.population AS POP, cRegions.temperature AS TEMP, cRegions.precipitation AS PREC, cRegions.mineralSolidity AS SOLI, cRegions.mineralValue AS VALU FROM cRegions WHERE cRegions.id = ?');
    $req->execute(array($regionId));
    $data = $req->fetch();
    
    $happiness = $data['HAP'];
    $population = $data['POP'];
    
    $temperature = $data['TEMP'];
    $precipitation = $data['PREC'];
    
    $mineralSolidity = $data['SOLI'];
    $mineralValue = $data['VALU'];

    $regionInfo["owner"] = $data['OWNER'];

    $deltaTime = $until - $data['TIME'];
    $time = $data['TIME'];
    
    //------------------------------------------------------------------------------------
    //Efficiency of agriculture and minerals
    //------------------------------------------------------------------------------------

    $efficiencies = [];
    $resources = getResourcesList();
    foreach ($resources as $key => $r) {
        
        if (is_int($key) && $key != 0) {
            $dTemperature = 0;
            if (array_key_exists("temperature", $r)) {
                $dTemperature = abs($temperature - $r["temperature"]) / 100;
            }
            $dPrecipitation = 0;
            if (array_key_exists("precipitation", $r)) {
                $dPrecipitation = abs($precipitation - $r["precipitation"]) / 100;
            }
            
            $dMineralSolidity = 0;
            if (array_key_exists("mineralSolidity", $r)) {
                $dMineralSolidity = abs($mineralSolidity - $r["mineralSolidity"]) / 100;
            }
            $dMineralValue = 0;
            if (array_key_exists("mineralValue", $r)) {
                $dMineralValue = abs($mineralValue - $r["mineralValue"]) / 100;
            }
            
            $dTot = $dTemperature*$dTemperature + $dPrecipitation*$dPrecipitation + $dMineralSolidity*$dMineralSolidity + $dMineralValue*$dMineralValue;
            $dTot = min($dTot, 1);
            
            $ratio = 1;
            if (array_key_exists("adaptability", $r) && array_key_exists("limitUp", $r) && array_key_exists("limitDown", $r)) {
                $ratio = pow((1-$dTot), $r["adaptability"]);
                
                if ($ratio > $r["limitUp"]) {
                    $ratio = 1;
                }
                else if ($ratio < $r["limitDown"]) {
                    $ratio = 0;
                }
            }
            
            $efficiencies[$key] = $ratio;
            
            if (array_key_exists("temperature", $r)) {
                $regionInfo["agricultureEfficiency"][$key] = $ratio;
            }
            else if (array_key_exists("mineralSolidity", $r)) {
                $regionInfo["mineralEfficiency"][$key] = $ratio;
            }
        }
    }

    if ($data['OWNER'] == 0) {
        return simulateInfluence($regionId, $until, $data['TIME'], $regionInfo);
    }

    //------------------------------------------------------------------------------------
    //Buildings
    //------------------------------------------------------------------------------------

    $localBuildings = [];
    $buildings = getBuildingsList();
    $techs = getTechsList();
    
    $req = $bdd->prepare('SELECT cBuildings.territory AS TERR, cBuildings.type AS BTYPE, cBuildings.production AS PROD, cDeposits.resource AS DEPR, cDeposits.concentration AS DEPC FROM cTerritories JOIN cBuildings on cTerritories.id = cBuildings.territory LEFT JOIN cDeposits ON cTerritories.id = cDeposits.territory WHERE cTerritories.id >= ? AND cTerritories.id <= ?');
    $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId)));
    while ($data = $req->fetch()) {
        $localBuildings[] = $data['TERR'];

        $building = $buildings[$data['BTYPE']];
        $resourceName = $resources[$data['PROD']]["shortName"];

        $regionInfo["buildingsEfficiency"][$data['TERR']] = 1;
        $regionInfo["buildingsProductionResource"][$data['TERR']] = $data['PROD'];
        $regionInfo["buildingsMaintenance"][$data['TERR']] = $building["maintenance"];
        
        //Adjacent buildings
        $adjacentRatioProduction = 1;
        $nei = getNeighbourgs($data['TERR']);
        
        foreach ($nei as $idNei) {
            $req2 = $bdd->prepare('SELECT cBuildings.type AS BTYPE FROM cBuildings WHERE cBuildings.territory = ?');
            $req2->execute(array($idNei));

            if ($data2 = $req2->fetch()) {
                $bonusMalus = buildingBonuses($buildings[$data2['BTYPE']]["color"], $building["color"]);

                $adjacentRatioProduction += $bonusMalus["production"];
                $regionInfo["buildingsAdjacentHappiness"][$data['TERR']] += $bonusMalus["happiness"];
            }
        }

        if (array_key_exists("population", $building)) { //population buildings
            $regionInfo["buildingsPopulation"][$data['TERR']] += $building["population"];
        }
        else if (array_key_exists("happiness", $building)) { //happiness buildings
            $regionInfo["buildingsHappiness"][$data['TERR']] += $building["happiness"];
        }
        else if (array_key_exists("techPower", $building)) { //Tech
            $regionInfo["buildingsTechProgressPerSec"][$data['TERR']] = $building["techPower"] * $adjacentRatioProduction;
        }
        else if (array_key_exists("production", $building)) { //Production
            
            $regionInfo["buildingsProductionAmount"][$data['TERR']] = prodPerSec($building["production"][$resourceName]["amount"]);

            if (empty($building["production"][$resourceName]["resourcesNeeded"])) { // mines or farms
                
                $depositRatio = 1;
                if (array_key_exists("deposit", $resources[$data['PROD']]) && $resources[$data['PROD']]["deposit"]) {
                    $r = nullIsZero($data['DEPR']);
                    if ($r != $data['PROD']) { //deposits does not exist or not the right type
                        $depositRatio = 0;
                    }
                    else {
                        $depositRatio = $data['DEPC'] / 100;
                    }
                }
                $regionInfo["buildingsEfficiency"][$data['TERR']] = $efficiencies[$data['PROD']] * $depositRatio * $adjacentRatioProduction;
            }
            else { //plants

                $regionInfo["buildingsResourcesNeeded"][$data['TERR']] = [];
                
                foreach($building["production"][$resourceName]["resourcesNeeded"] as $key => $resourceNeeded) {
                    $regionInfo["buildingsResourcesNeeded"][$data['TERR']][getResourceId($key)] = prodPerSec($resourceNeeded);
                }
                
                $regionInfo["buildingsEfficiency"][$data['TERR']] = $adjacentRatioProduction;
            }
        }
    }

    //------------------------------------------------------------------------------------
    //Current resources and techs
    //------------------------------------------------------------------------------------


    $req = $bdd->prepare('SELECT * FROM cRegionResources WHERE region = ?');
    $req->execute(array($regionId));
    while ($data = $req->fetch()) {
        $regionInfo["current"][$data['resource']] = $data['amount'];
    }
    
    $req = $bdd->prepare('SELECT * FROM cResearch WHERE territory >= ? AND territory <= ?');
    $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId)));
    while ($data = $req->fetch()) {
        $regionInfo["buildingsTech"][$data['territory']] = $data['tech'];
        $regionInfo["buildingsTechProgress"][$data['territory']] = $data['progress'];
        $regionInfo["buildingsTechTimeBegun"][$data['territory']] = $data['timeBegun'];
        $regionInfo["buildingsTechTimeFinished"][$data['territory']] = $data['timeFinished'];
    }

    //------------------------------------------------------------------------------------
    //Actual simulation
    //------------------------------------------------------------------------------------
    $totalFundsGained = 0;
    $t = $time;
    $consumption = getConsumption($regionId, $techs);
    do {
        //calculate derivatives
        $regionInfo["gained"] = [];
        $regionInfo["fundsGained"] = 0;
        $theoreticalHappiness = 60;
        $theoreticalPopulation = 10;

        //Buildings
        foreach ($localBuildings as $building) {
            
            $theoreticalHappiness += $regionInfo["buildingsAdjacentHappiness"][$building];
            $regionInfo["fundsGained"] -= prodPerSec($regionInfo["buildingsMaintenance"][$building]);

            $resource = $regionInfo["buildingsProductionResource"][$building];
            $amount = $regionInfo["buildingsProductionAmount"][$building];
            $efficiency = $regionInfo["buildingsEfficiency"][$building];
            
            if ($resource == 0) {
                $theoreticalPopulation += $regionInfo["buildingsPopulation"][$building];
                $theoreticalHappiness += $regionInfo["buildingsHappiness"][$building];
            }
            else if (empty($regionInfo["buildingsResourcesNeeded"][$building])) { //mine or farm
                $regionInfo["gained"][$resource] += $amount * $efficiency;
            }
            else {
                $minRatio = $efficiency;
                foreach ($regionInfo["buildingsResourcesNeeded"][$building] as $r => $a) {
                    if ($regionInfo["current"][$r] > 0) {
                        //do not decrease ratio
                    }
                    else {
                        $minRatio = min($minRatio, $regionInfo["gained"][$r] / $a);
                    }
                }

                foreach ($regionInfo["buildingsResourcesNeeded"][$building] as $r => $a) {
                    $regionInfo["gained"][$r] -= $a * $minRatio;
                }
                $regionInfo["gained"][$resource] += $amount * $minRatio;
            }
        }

        //Consumption

        foreach ($consumption as $type => $data) {
            $num = 0;
            foreach ($resources as $key => $r) {
                if (is_int($key) && $key > 0 && $r['type'] == $type && $regionInfo["current"][$key] > 0) {
                    $num++;
                }
            }

            if ($num == 0) { //no reserves
                $sumGained = 0;
                foreach ($resources as $key => $r) {
                    if (is_int($key) && $key > 0 && $r['type'] == $type) {
                        $sumGained += $regionInfo["gained"][$key]; //always positive
                    }
                }

                if ($sumGained > 0) {
                    $ratio = prodPerSec($data['amount']) * intval($population) / $sumGained;

                    if ($ratio <= 1) { //enough production
                        foreach ($resources as $key => $r) {
                            if (is_int($key) && $key > 0 && $r['type'] == $type) {
                                $regionInfo["gained"][$key] -= $ratio * $regionInfo["gained"][$key] * $r["consumptionValue"];
                            }
                        }
                    }
                    else { //production not enough
                        foreach ($resources as $key => $r) { 
                            if (is_int($key) && $key > 0 && $r['type'] == $type) {
                                $regionInfo["gained"][$key] = 0;
                            }
                        }

                        $theoreticalHappiness -= $data['malus'] * ($ratio - 1) / $ratio; //stays between 0 and 1
                    }
                }
                else { //no production
                    $theoreticalHappiness -= $data['malus'];
                }
            }
            else { //reserves
                foreach ($resources as $key => $r) {
                    if (is_int($key) && $key > 0 && $r['type'] == $type && $regionInfo["current"][$key] > 0) {
                        $regionInfo["gained"][$key] -= prodPerSec($data['amount']) * intval($population) * $r["consumptionValue"] / $num;
                    }
                }
            }
        }
        
        //Population taxes
        $regionInfo["fundsGained"] += intval($population) * getPopulationTaxRate();

        //get next t
        $dt = $until - $t;

        foreach ($regionInfo["current"] as $key => $amount) {
            if ($amount > 0 && $regionInfo["gained"][$key] < 0) {
                $dt = min($dt, -$amount / $regionInfo["gained"][$key]);
            }
        }

        //Happiness
        if (abs($happiness - $theoreticalHappiness) < 0.000001) {
            $regionInfo["happinessGrowth"] = 0;
        }
        else if ($theoreticalHappiness > $happiness) {
            $regionInfo["happinessGrowth"] = prodPerSec(getHappinessGrowth());
        }
        else {
            $regionInfo["happinessGrowth"] = -prodPerSec(getHappinessGrowth());
        }
        $dt = min($dt, timeToNextLevel($regionInfo["happinessGrowth"], $happiness, getHappinessLevelInferior($happiness), getHappinessLevelSuperior($happiness)));

        //Population
        if (abs($population - $theoreticalPopulation) < 0.000001 && $happiness >= 30) {
            $regionInfo["populationGrowth"] = 0;
        }
        else if ($theoreticalPopulation > $population && $happiness >= 60) {
            $regionInfo["populationGrowth"] = prodPerSec(getPopulationGrowth());
        }
        else if ($theoreticalPopulation > $population && $happiness >= 30) {
            $regionInfo["populationGrowth"] = 0;
        }
        else {
            $regionInfo["populationGrowth"] = -prodPerSec(getPopulationGrowth());
        }

        if (intval($population) - $population < 0.00001) {
            $dt = min($dt, timeToNextLevel($regionInfo["populationGrowth"], $population, intval($population) - 1, intval($population) + 1));
        }
        else {
            $dt = min($dt, timeToNextLevel($regionInfo["populationGrowth"], $population, floor($population), ceil($population)));
        }

        if ($dt == 0) {
            $dt = 1;
        }

        //simulate

        foreach ($regionInfo["gained"] as $key => $amount) {
            $regionInfo["current"][$key] += $amount * $dt;
        }
        $totalFundsGained += $regionInfo["fundsGained"] * $dt;

        //Tech
        foreach ($localBuildings as $building) {
            if ($regionInfo["buildingsTech"][$building] != 0) {
                $regionInfo["buildingsTechProgress"][$building] += $regionInfo["buildingsTechProgressPerSec"][$building] * $dt;
            }
        }

        $happiness += $regionInfo["happinessGrowth"] * $dt;
        $happiness = max(min($happiness, 100), 0);

        $population += $regionInfo["populationGrowth"] * $dt;
        if ($population < 10) {
            $population = 10;
            $regionInfo["populationGrowth"] = 0;
        }

        $t += $dt;

        $req = $bdd->prepare('SELECT * FROM cSingleton');
        $req->execute(array());
        $data = $req->fetch();

        if ($data['val'] != 1) {
            exit;
        }

    } while ($t < $until);

    //------------------------------------------------------------------------------------
    //Update
    //------------------------------------------------------------------------------------

    addFundsFromRegion($regionId, $totalFundsGained);

    $regionInfo["happiness"] = $happiness;
    $regionInfo["population"] = $population;        
    
    $req = $bdd->prepare('UPDATE cRegions SET time = ? WHERE cRegions.id = ?');
    $req->execute(array($until, $regionId));
    
    $req = $bdd->prepare('UPDATE cRegions SET happiness = ? WHERE cRegions.id = ?');
    $req->execute(array($happiness, $regionId));
    
    $req = $bdd->prepare('UPDATE cRegions SET population = ? WHERE cRegions.id = ?');
    $req->execute(array($population, $regionId));

    foreach ($regionInfo["current"] as $key => $amount) {
        setResourcesInRegion($regionId, $key, $amount);
    }

    //Tech
    foreach ($localBuildings as $building) {
        if ($regionInfo["buildingsTech"][$building] != 0) {
            $req = $bdd->prepare('UPDATE cResearch SET progress = ?, timeFinished = ? WHERE territory = ?');
            $req->execute(array($regionInfo["buildingsTechProgress"][$building], $until + max((hourToSec($techs[$regionInfo["buildingsTech"][$building]]['time']) - $regionInfo["buildingsTechProgress"][$building])/ $regionInfo["buildingsTechProgressPerSec"][$building], 0), $building));
        }
    }

    return $regionInfo;
}

/*function simulateRegionOld($regionId, $until) {
    global $bdd;
    
    $regionResources = [
        "current" => [],
        "gained" => [],
        "populationConsumption" => [],
        "owner" => 0,
        "currentInfluences" => [],
        "gainedInfluences" => [],
        "agricultureEfficiency" => [],
        "mineralEfficiency" => [],
        "buildingsEfficiency" => [],
        "happiness" => 0,
        "happinessGrowth" => 0,
        "happinessBonus" => 0,
        "population" => 0,
        "populationGrowth" => 0
    ];
    
    $req = $bdd->prepare('SELECT cRegions.time AS TIME, cRegions.owner AS OWNER, cRegions.happiness AS HAP, cRegions.population AS POP, cRegions.temperature AS TEMP, cRegions.precipitation AS PREC, cRegions.mineralSolidity AS SOLI, cRegions.mineralValue AS VALU FROM cRegions WHERE cRegions.id = ?');
    $req->execute(array($regionId));
    $data = $req->fetch();
    
    $happiness = $data['HAP'];
    $population = $data['POP'];
    
    $temperature = $data['TEMP'];
    $precipitation = $data['PREC'];
    
    $mineralSolidity = $data['SOLI'];
    $mineralValue = $data['VALU'];

    $regionResources["owner"] = $data['OWNER'];

    $deltaTime = $until - $data['TIME'];
    $time = $data['TIME'];
    
    //Efficiency of agriculture and minerals
    $efficiencies = [];
    $resources = getResourcesList();
    foreach ($resources as $key => $r) {
        
        if (is_int($key) && $key != 0) {
            $dTemperature = 0;
            if (array_key_exists("temperature", $r)) {
                $dTemperature = abs($temperature - $r["temperature"]) / 100;
            }
            $dPrecipitation = 0;
            if (array_key_exists("precipitation", $r)) {
                $dPrecipitation = abs($precipitation - $r["precipitation"]) / 100;
            }
            
            $dMineralSolidity = 0;
            if (array_key_exists("mineralSolidity", $r)) {
                $dMineralSolidity = abs($mineralSolidity - $r["mineralSolidity"]) / 100;
            }
            $dMineralValue = 0;
            if (array_key_exists("mineralValue", $r)) {
                $dMineralValue = abs($mineralValue - $r["mineralValue"]) / 100;
            }
            
            $dTot = $dTemperature*$dTemperature + $dPrecipitation*$dPrecipitation + $dMineralSolidity*$dMineralSolidity + $dMineralValue*$dMineralValue;
            $dTot = min($dTot, 1);
            
            $ratio = 1;
            if (array_key_exists("adaptability", $r) && array_key_exists("limitUp", $r) && array_key_exists("limitDown", $r)) {
                $ratio = pow((1-$dTot), $r["adaptability"]);
                
                if ($ratio > $r["limitUp"]) {
                    $ratio = 1;
                }
                else if ($ratio < $r["limitDown"]) {
                    $ratio = 0;
                }
            }
            
            $efficiencies[$key] = $ratio;
            
            if (array_key_exists("temperature", $r)) {
                $regionResources["agricultureEfficiency"][$key] = $ratio;
            }
            else if (array_key_exists("mineralSolidity", $r)) {
                $regionResources["mineralEfficiency"][$key] = $ratio;
            }
        }
    }

    if ($data['OWNER'] == 0) {
        return simulateInfluence($regionId, $until, $data['TIME'], $regionResources);
    }
    
    if ($deltaTime > 0) {
        $theoreticalHappiness = 30;
        
        $theoreticalPopulation = 10;
        $buildings = getBuildingsList();
        
        //Construction
        
        $buildingTimes = [];
        
        $req = $bdd->prepare('SELECT * FROM cBuildingConstructions WHERE territory >= ? AND territory <= ? AND timeFinished <= ?');
        $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId), $until));
        
        while ($data = $req->fetch()) {
            $production = 0;
            
            if (array_key_exists("production", $buildings[$data['type']])) {
                foreach ($buildings[$data['type']]["production"] as $key => $prod) {
                    $production = getResourceId($key);
                }
            }
            
            $req2 = $bdd->prepare('INSERT INTO cBuildings (territory, type, production) VALUES(?, ?, ?)');
            $req2->execute(array($data['territory'], $data['type'], $production));
            
            $buildingTimes[$data['territory']] = $data['timeFinished'];
            
            $req2 = $bdd->prepare('DELETE FROM cBuildingConstructions WHERE territory = ?');
            $req2->execute(array($data['territory']));
            
            
        }
        //Production/Population/Happiness
        
        $req = $bdd->prepare('SELECT cBuildings.territory AS TERR, cBuildings.type AS BTYPE, cBuildings.production AS PROD, cDeposits.resource AS DEPR, cDeposits.concentration AS DEPC FROM cTerritories JOIN cBuildings on cTerritories.id = cBuildings.territory LEFT JOIN cDeposits ON cTerritories.id = cDeposits.territory WHERE cTerritories.id >= ? AND cTerritories.id <= ?');
        $req->execute(array(getMinTerritoryId($regionId), getMaxTerritoryId($regionId)));
        while ($data = $req->fetch()) {
            $ownDeltaTime = $deltaTime;
            
            if (array_key_exists($data['TERR'], $buildingTimes)) { // if building was constructed during this simulation
                $ownDeltaTime = $until - $buildingTimes[$data['TERR']];
            }
            
            $regionResources["buildingsEfficiency"][$data['TERR']] = 1;
            
            $building = $buildings[$data['BTYPE']];
            $resourceName = $resources[$data['PROD']]["shortName"];
            
            //Adjacent buildings
            $adjacentRatioProduction = 1;
            $nei = getNeighbourgs($data['TERR']);
            
            foreach ($nei as $idNei) { //OPTI : cache all buildings (/!\ out of region buildings)
                $req2 = $bdd->prepare('SELECT cBuildings.type AS BTYPE FROM cBuildings WHERE cBuildings.territory = ?');
                $req2->execute(array($idNei));

                if ($data2 = $req2->fetch()) {
                    $bonusMalus = buildingBonuses($buildings[$data2['BTYPE']]["color"], $building["color"]);

                    $adjacentRatioProduction += $bonusMalus["production"];
                    $theoreticalHappiness += $bonusMalus["happiness"];
                }
            }

            if (array_key_exists("population", $building)) { //population buildings
                $theoreticalPopulation += $building["population"];
            }
            else if (array_key_exists("happiness", $building)) { //happiness buildings
                $theoreticalHappiness += $building["happiness"];
            }
            else if (array_key_exists("production", $building)) { //Production
                if (empty($building["production"][$resourceName]["resourcesNeeded"])) { // mines or farms
                    $amount = prodPerSec($building["production"][$resourceName]["amount"]) * $ownDeltaTime;
                    
                    $depositRatio = 1;
                    if (array_key_exists("deposit", $resources[$data['PROD']]) && $resources[$data['PROD']]["deposit"]) {
                        $r = nullIsZero($data['DEPR']);
                        if ($r != $data['PROD']) { //deposits does not exist or not the right type
                            $depositRatio = 0;
                        }
                        else {
                            $depositRatio = $data['DEPC'] / 100;
                        }
                    }
                    
                    $amount *= $efficiencies[$data['PROD']] * $depositRatio * $adjacentRatioProduction;
                    $regionResources["buildingsEfficiency"][$data['TERR']] = $efficiencies[$data['PROD']] * $depositRatio * $adjacentRatioProduction;
                
                    addResourcesInRegion($regionId, $data['PROD'], $amount);
                    
                    $regionResources["gained"][$data['PROD']] += $amount / $ownDeltaTime;
                }
                else { //plants
                    $minRatio = 1;
                    
                    foreach($building["production"][$resourceName]["resourcesNeeded"] as $key => $resourceNeeded) {
                        $currentAmount = resourcesInRegion($regionId, getResourceId($key));
                        $neededAmount = prodPerSec($resourceNeeded) * $ownDeltaTime * $adjacentRatioProduction;
                        
                        $minRatio = min($minRatio, $currentAmount / $neededAmount);
                    }
                    
                    if ($minRatio > 0) { // no need to update if no changes
                        foreach($building["production"][$resourceName]["resourcesNeeded"] as $key => $resourceNeeded) {
                            $usedAmount = $minRatio * prodPerSec($resourceNeeded) * $ownDeltaTime * $adjacentRatioProduction;
                            
                            removeResourcesInRegion($regionId, getResourceId($key), $usedAmount);
                            $regionResources["gained"][getResourceId($key)] -= $usedAmount / $ownDeltaTime;
                        }
                        $amount = prodPerSec($building["production"][$resourceName]["amount"]) * $ownDeltaTime * $minRatio * $adjacentRatioProduction;
                        
                        addResourcesInRegion($regionId, $data['PROD'], $amount);
                        $regionResources["gained"][$data['PROD']] += $amount / $ownDeltaTime;
                    }
                }
            }
            
        }
        
        $consumption = getConsumption(2); // TODO : maybe lvl will change during simulation
        $consumptionResources = [];
        
        $req = $bdd->prepare('SELECT * FROM cRegionResources WHERE region = ?');
        $req->execute(array($regionId));
        while ($data = $req->fetch()) {
            $type = $resources[$data['resource']]['type'];
            
            if (!array_key_exists($type, $consumptionResources)) {
                $consumptionResources[$type] = [];
            }
            
            $consumptionResources[$type][$data['resource']] = $data['amount'];
        }
        
        $step = 60;
        $t = $time;
        
        $done = false;
        while (!$done) {
            if ($until - $t > $step) {
                $dt = $step;
                $t += $step;
            }
            else {
                $dt = $until - $t;
                $done = true;
            }
            
            //------------------------------------------------------------------------
            //Population consumption
            //------------------------------------------------------------------------
            
            $consumptionHappiness = 0;
            
            foreach($consumption as $type => $tab) {
                $sum = 0;
                
                if (array_key_exists($type, $consumptionResources)) {
                    foreach($consumptionResources[$type] as $r => $q) {
                        $sum += $q / $resources[$r]["consumptionValue"];
                    }
                }
                
                $needed = intval($population) * prodPerSec($tab["amount"]) * $dt;
                
                if ($sum == 0) {
                    //TODO : maybe display message ?
                }
                else if ($needed > $sum) {
                    $ratio = $needed / $sum;
                    
                    foreach($consumptionResources[$type] as $r => $q) {
                        $consumptionResources[$type][$r] = 0;
                        
                        $regionResources["populationConsumption"][$r] = - $ratio * $q * $resources[$r]["consumptionValue"] / $dt;
                    }
                    
                    $consumptionHappiness -= $tab["malus"];
                }
                else {
                    $ratio = $needed / $sum;
                    
                    foreach($consumptionResources[$type] as $r => $q) {
                        $consumptionResources[$type][$r] -= $ratio * $q * $resources[$r]["consumptionValue"];
                        $regionResources["populationConsumption"][$r] = - $ratio * $q * $resources[$r]["consumptionValue"] / $dt;
                    }
                }
            }
            
            //------------------------------------------------------------------------
            //Happiness
            //------------------------------------------------------------------------

            
            $newHappiness = $theoreticalHappiness + $consumptionHappiness;
            
            if (abs($happiness - $newHappiness) < 0.000001) {
                $happiness = $newHappiness;
                $regionResources["happinessGrowth"] = 0;
            }
            else if ($newHappiness > $happiness) {
                $happiness += $dt * getHappinessGrowth();
                $regionResources["happinessGrowth"] = prodPerHour(getHappinessGrowth());
                $happiness = min($happiness, $newHappiness);
            }
            else if ($newHappiness < $happiness) {
                $happiness -= $dt * getHappinessGrowth();
                $regionResources["happinessGrowth"] = -prodPerHour(getHappinessGrowth());
                $happiness = max($happiness, $newHappiness);
            }
            
            $happiness = max(min($happiness, 100), 0);
            
            
            //------------------------------------------------------------------------
            //Population
            //------------------------------------------------------------------------
            
            $newPopulation = $theoreticalPopulation * (1 + max(($happiness - 80), 0) / 50);
            
            if (abs($population - $newPopulation) < 0.000001) {
                $population = $newPopulation;
                $regionResources["populationGrowth"] = 0;
            }
            else if ($newPopulation > $population) {
                $population += $deltaTime * getPopulationGrowth() * max(($happiness - 60), 0);
                $regionResources["populationGrowth"] = prodPerHour(getPopulationGrowth() * max(($happiness - 60), 0));
                $population = min($population, $newPopulation);
            }
            else if ($newPopulation < $population) {
                $population -= $deltaTime * getPopulationGrowth();
                $regionResources["populationGrowth"] = -prodPerHour(getPopulationGrowth());
                $population = max($population, $newPopulation);
            }
            $population = max($population, 1);
        }
        
        foreach($consumption as $type => $amount) {
            if (array_key_exists($type, $consumptionResources)) {
                foreach($consumptionResources[$type] as $r => $q) {
                    setResourcesInRegion($regionId, $r, $q);
                }
            }
        }
        
        $regionResources["happiness"] = $happiness;
        $regionResources["population"] = $population;        
        
        $req = $bdd->prepare('UPDATE cRegions SET time = ? WHERE cRegions.id = ?');
        $req->execute(array($until, $regionId));
        
        $req = $bdd->prepare('UPDATE cRegions SET happiness = ? WHERE cRegions.id = ?');
        $req->execute(array($happiness, $regionId));
        
        $req = $bdd->prepare('UPDATE cRegions SET population = ? WHERE cRegions.id = ?');
        $req->execute(array($population, $regionId));
    }
    
    $req = $bdd->prepare('SELECT * FROM cRegionResources WHERE region = ?');
    $req->execute(array($regionId));
    while ($data = $req->fetch()) {
        $regionResources["current"][$data['resource']] = $data['amount'];
    }
    
    return $regionResources;
}*/

function simulateInfluence($regionId, $until, $time, $regionInfo) {
    global $bdd;
    
    $buildings = getBuildingsList();

    $deltaTime = $until - $time;
    $dInfluences = [];

    $gains = [];
    $current = [];

    $x = getRegionX($regionId);
    $y = getRegionY($regionId);

    for ($i = -1; $i <= 1; $i++) {
        for ($j = -1; $j <= 1; $j++) {
            $req = $bdd->prepare('SELECT cRegions.owner FROM cRegions WHERE cRegions.id = ?');
            $req->execute(array(getRegionId($x + $i, $y + $j)));
            $data = $req->fetch();

            if ($data['owner'] != 0) {
                $dInfluences[$data['owner']] += 1;
            }
        }
    }
    
    foreach($buildings as $key => $building) {
        if (array_key_exists("influence", $building)) {
            $regionInfo['buildingInfluences'][$key] = [];
            $amount = $building['influence']['amount'];
            $column = $building['influence']['column'];
            
            $req = $bdd->prepare('SELECT cInfluences.user, cBuildings.type, cInfluences.' . $column . ' FROM cInfluences LEFT JOIN cBuildings ON cInfluences.' . $column . ' = cBuildings.territory WHERE cInfluences.region = ?');
            $req->execute(array($regionId));
            while ($data = $req->fetch()) {
                
                if (nullIsZero($data['type']) != 0) {
                    $dInfluences[$data['user']] += $amount;
                }
                if (nullIsZero($data[$column]) != 0) {
                    $regionInfo['buildingInfluences'][$key][$data['user']] = true;
                }
            }
        }
    }
    
    

    $maxVal = 0;
    $max = 0;

    $secondMax = 0;
    $secondMaxVal = 0;
    foreach ($dInfluences as $user => $value) {
        $value *= getInfluenceGrowth();
        if ($value > $maxVal) {
            $secondMax = $max;
            $secondMaxVal = $maxVal;

            $maxVal = $value;
            $max = $user;
        }
        else if ($value > $secondMaxVal) {
            $secondMaxVal = $value;
            $secondMax = $user;
        }
    }

    $dMaxVal = $maxVal - $secondMaxVal;

    if ($max != 0) {
        addInfluenceInRegion($regionId, $max, $dMaxVal * $deltaTime);
        $gains[$max] = $dMaxVal;

        $influences = [];
        $sum = 0;
        $req = $bdd->prepare('SELECT cInfluences.user, cInfluences.value FROM cInfluences WHERE cInfluences.region = ?');
        $req->execute(array($regionId));
        while ($data = $req->fetch()) {
            if ($data['user'] != $max) {
                $influences[$data['user']] = $data['value'];
                $sum += $data['value'];
            }
        }

        if ($sum != 0) {
            foreach ($influences as $user => $value) {
                removeInfluenceInRegion($regionId, $user, $dMaxVal * $value * $deltaTime / $sum);
                $gains[$user] = -$dMaxVal * $value / $sum;
            }
        }
    }

    //Update gains and current influence

    foreach ($gains as $key => $value) {
        $req = $bdd->prepare('SELECT pseudo FROM cUsers WHERE cUsers.id = ?');
        $req->execute(array($key));
        $data = $req->fetch();

        $regionInfo["gainedInfluences"][$data['pseudo']] = $value;
    }

    $req = $bdd->prepare('SELECT cUsers.pseudo, cUsers.id, cInfluences.value FROM cInfluences JOIN cUsers ON cInfluences.user = cUsers.id WHERE cInfluences.region = ?');
    $req->execute(array($regionId));
    while ($data = $req->fetch()) {
        $regionInfo["currentInfluences"][$data['pseudo']] = $data['value'];
        $regionInfo["currentInfluencesId"][$data['id']] = $data['value'];
    }

    $req = $bdd->prepare('UPDATE cRegions SET time = ? WHERE cRegions.id = ?');
    $req->execute(array($until, $regionId));

    return $regionInfo;
}

?>