1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
<?php
namespace App\Model\Event;
use App\DB;
use App\Model\Event;
use App\Model\Unit;
use App\Model\Unit\Merchant;
use App\Model\Village;
class SendResourcesMerchants extends BaseEvent
{
public int $wood = 0;
public int $clay = 0;
public int $iron = 0;
public int $food = 0;
public int $source;
public int $destination;
public bool $isCanceled = false;
/**
* @return void
*/
public function __invoke(): void
{
if ($this->isCanceled) {
// TODO: switch destination and source
// TODO: add resources back to "destination"
// TODO: add merchants back to "destination"
}
else {
// TODO: account for storage capacity
DB::query(
'update villages set wood=wood+:wood, clay=clay+:clay, iron=iron+:iron, food=food+:food where id=:id',
[
'wood' => $this->wood,
'clay' => $this->clay,
'iron' => $this->iron,
'food' => $this->food,
'id' => $this->destination,
]
);
// TODO: foreach send_resources_merchants
$source = Village::get($this->source);
$destination = Village::get($this->destination);
$event = new Event();
$event->time = (new \DateTime())->add(
\DateInterval::createFromDateString(
Unit::getTravelTime(new Merchant(), Village::getDistance($source->x, $source->y, $destination->x, $destination->y))
. ' seconds'
)
);
$event->villageId = $this->source;
$sendUnitsEvent = new SendUnits();
$sendUnitsEvent->event = $event;
$sendUnitsEvent->type = 'SendBack';
$sendUnitsEvent->unit = 'Merchant';
$sendUnitsEvent->amount = $amount;
$sendUnitsEvent->source = $village->id;
$sendUnitsEvent->destination = $destination->id;
$sendUnitsEvent->dbInsert();
// TODO: add resources to destination
// (TODO: add foreign merchants to destination)?
// TODO: create SendUnits event with merchants back to source
}
}
public function dbInsert(int $previouId): void
{
DB::query(
'update events_send_resources_merchants set event_id=:new_id where event_id=:old_id',
['old_id' => $previouId, 'new_id' => $this->id]
);
/*
DB::query(
'insert into events (time, village_id) VALUES (:time, :village_id)',
['time' => $this->event->time->format('c'), 'village_id' => $this->event->villageId]
);
DB::query(
<<<SQL
insert into events_send_resources (event_id, wood, clay, iron, food, source, destination, is_canceled)
VALUES (:event_id, :wood, :clay, :iron, :food, :source, :destination, :is_canceled)
SQL,
[
'event_id' => DB::$connection->lastInsertId(),
'wood' => $this->wood,
'clay' => $this->clay,
'iron' => $this->iron,
'food' => $this->food,
'source' => $this->source, 'destination' => $this->destination,
'is_canceled' => $this->isCanceled ?: 0, // @see https://www.php.net/manual/de/pdostatement.execute.php#126013
]
);
$sendResourcesEventId = DB::$connection->lastInsertId();
$resourceCapabilities = Merchant::getResourceCapabilities($this->event->villageId);
$resourcesTotal = $this->wood + $this->clay + $this->iron + $this->food;
$necessaryMerchants = ceil($resourcesTotal / $resourceCapabilities);
$merchantsAccountedFor = 0;
while ($merchantsAccountedFor < $necessaryMerchants) {
$merchants = DB::fetch(
Merchant::class,
'select * from village_units where type=:type and residence_village_id=:villageId and is_traveling=false',
['type' => 'Merchant', 'villageId' => $this->source]
);
foreach ($merchants as $merchant) {
$currentlyNecessaryMerchants = $necessaryMerchants - $merchantsAccountedFor;
$currentlyUseableMerchants = $currentlyNecessaryMerchants - $merchant->amount < 0 ? $currentlyNecessaryMerchants : $merchant->amount;
$merchantsAccountedFor += $currentlyUseableMerchants;
DB::query(
<<<SQL
insert into village_units (amount, type, is_traveling, home_village_id, residence_village_id)
VALUES (:amount, :type, true, :home, :residence)
on conflict (type, home_village_id, residence_village_id, is_traveling)
do update set is_traveling=true
SQL,
[
'amount' => $currentlyUseableMerchants,
'type' => 'Merchant',
'home' => $merchant->homeVillageId,
'residence' => $merchant->residenceVillageId,
]
);
DB::query('update village_units set amount=amount-:amount where id=:unitId', ['amount' => $necessaryMerchants, 'unitId' => $merchant->id]);
DB::query(
<<<SQL
insert into events_send_resources_merchants (event_id, unit_id, amount)
VALUES (:event_id, :unit_id, :amount)
SQL,
[
'event_id' => $sendResourcesEventId,
'unit_id' => $merchant->id,
'amount' => $necessaryMerchants,
]
);
}
}*/
}
public function dbDelete(): void
{
DB::query('delete from events_send_resources_merchants where event_id=:id', ['id' => $this->id]);
}
}
|