diff options
| -rw-r--r-- | Justfile | 3 | ||||
| -rw-r--r-- | bin/db.php | 51 | ||||
| -rw-r--r-- | docker-compose.yml | 2 | ||||
| -rw-r--r-- | docker/adminer.css | 113 | ||||
| -rw-r--r-- | src/Model/Building/Marketplace.php | 10 | ||||
| -rw-r--r-- | src/Model/Event/SendResources.php | 150 | ||||
| -rw-r--r-- | src/Model/Event/SendResourcesMerchants.php | 154 | ||||
| -rw-r--r-- | src/Model/Unit/Merchant.php | 8 | ||||
| -rw-r--r-- | src/Model/Village.php | 30 | ||||
| -rw-r--r-- | src/gemini/Controller/Village.php | 88 | ||||
| -rw-r--r-- | src/gemini/Gemini.php | 19 | ||||
| -rw-r--r-- | views/gemini/send-resources/01-resource-types.twig | 4 | ||||
| -rw-r--r-- | views/gemini/send-resources/02-villages.twig | 6 | ||||
| -rw-r--r-- | views/gemini/send-units/02-villages.twig | 2 | ||||
| -rw-r--r-- | views/gemini/village.twig | 33 | 
15 files changed, 662 insertions, 11 deletions
| @@ -1,2 +1,5 @@ +db: +  docker compose exec app php bin/db.php +  gemini:    find $(pwd) -type f -name '*.php' -o -name '*.twig' | GEMINI=true DB_HOST=localhost entr -r php public/index.php @@ -88,7 +88,9 @@ DB::query(<<<SQL        foreign key ("village_id") references villages("id") on delete cascade,      "created_at" timestamp(0) not null default current_timestamp, -    "updated_at" timestamp(0) not null default current_timestamp +    "updated_at" timestamp(0) not null default current_timestamp, + +    unique ("village_id")    );  SQL); @@ -181,6 +183,53 @@ DB::query(<<<SQL  SQL);  DB::query(<<<SQL +  create table if not exists "events_send_resources" ( +    "id" bigserial primary key, + +    "event_id" bigint not null, +    constraint "relation_event" +      foreign key ("event_id") references events("id") on delete cascade, + +    "wood" bigint not null, +    "clay" bigint not null, +    "iron" bigint not null, +    "food" bigint not null, + +    "is_canceled" boolean not null default false, + +    "source" bigint not null, +    constraint "relation_village_source" +      foreign key ("source") references villages("id"), + +    "destination" bigint not null, +    constraint "relation_village_destination" +      foreign key ("destination") references villages("id"), + +    "created_at" timestamp(0) not null default current_timestamp, +    "updated_at" timestamp(0) not null default current_timestamp +  ); +SQL); + +DB::query(<<<SQL +  create table if not exists "events_send_resources_merchants" ( +    "id" bigserial primary key, + +    "event_id" bigint not null, +    constraint "relation_event" +      foreign key ("event_id") references events_send_resources("id") on delete cascade, + +    "unit_id" bigint not null, +    constraint "relation_unit" +      foreign key ("unit") references village_units("id"), + +    "amount" bigint not null, + +    "created_at" timestamp(0) not null default current_timestamp, +    "updated_at" timestamp(0) not null default current_timestamp +  ); +SQL); + +DB::query(<<<SQL    create table if not exists "users" (      "id" bigserial primary key, diff --git a/docker-compose.yml b/docker-compose.yml index 154d35f..c2a6b6a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,6 +44,8 @@ services:        - "8081:8080"      environment:        - "ADMINER_DEFAULT_SERVER=db" +    volumes: +      - "./docker/adminer.css:/var/www/html/adminer.css"  volumes:    db: diff --git a/docker/adminer.css b/docker/adminer.css new file mode 100644 index 0000000..9f30efb --- /dev/null +++ b/docker/adminer.css @@ -0,0 +1,113 @@ +@media (prefers-color-scheme: dark) { +  body { +    background: #222; +    color: #ebebeb; +  } + +  a { +    &, &:visited { +      color: #ebebeb; +      background: transparent !important; + +      &:hover { +        color: #fff; +      } +    } +  } + +  h1, h2 { +    background: transparent; +    color: #ebebeb; +  } +  h2 { +    border-color: #999; +  } + +  #breadcrumb { +    background: transparent; +    margin: 0; +  } + +  #menu { +    width: 21em; +  } + +  #content { +    margin-left: 22em; +  } + +  .footer { +    border-top-color: transparent; +    border-image: none; + +    & > div { +      background: #222; +    } +  } + +  td, +  tbody th { +    background: transparent !important; +  } +  th, +  thead td, +  tr.checked td, +  tr:hover td { +    background: #333 !important; +  } +  td, th { +    padding: 0.1rem 0.4rem; +  } + +  .column { +    background: #222 !important; +  } + +  code { +    background: transparent; +    padding: 0.1rem 0.2rem; +  } +  .jush, .jush a { +    color: #ebebeb; +  } +  .jush-sqlite_quo { +    color: inherit; +  } +  .jush-num { +    color: inherit; +  } +  .jush-quo { +    color: inherit; +  } + +  .error, .message { +    background: #333; +    color: #ebebeb; + +    b { +      background: #222; +      padding: 0 0.2rem; +    } +  } + +  #help { +    background: #333; +  } + +  input, select { +    background: #333; +    color: #ebebeb; +    border: 1px solid #777; +  } + +  input[type="submit"] { +    cursor: pointer; +    padding: 0.1rem 0.4rem; +    line-height: 1rem; + +    &:hover { +      background: #ebebeb; +      color: #222; +    } +  } +} diff --git a/src/Model/Building/Marketplace.php b/src/Model/Building/Marketplace.php index 2d87379..8978003 100644 --- a/src/Model/Building/Marketplace.php +++ b/src/Model/Building/Marketplace.php @@ -3,9 +3,12 @@  namespace App\Model\Building;  use App\Model\Building; +use App\Model\Unit\Merchant; +use App\Model\Village;  class Marketplace extends Building  { +  public string $unitType = 'Merchant';    public int $buildTimeFactor = 1;    public int $maxLevel = 25; @@ -19,4 +22,11 @@ class Marketplace extends Building      'clay' => 10.0,      'iron' => 8.0,    ]; + +  public static function getResourceCapabilities(Village $village): int +  { +    $merchants = Village::getUnit($village, 'Merchant', Village::FETCH_UNIT_RESIDENCE, Village::RETURN_UNIT_EXISTING); + +    return Merchant::getResourceCapabilities($village) * $merchants->amount; +  }  } diff --git a/src/Model/Event/SendResources.php b/src/Model/Event/SendResources.php new file mode 100644 index 0000000..5c751fd --- /dev/null +++ b/src/Model/Event/SendResources.php @@ -0,0 +1,150 @@ +<?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 SendResources 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, +        ] +      ); + +      $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; + +      $sendResourcesMerchants = new SendResourcesMerchants(); +      $sendResourcesMerchants->dbInsert($this->id); + + +      // TODO: add resources to destination +      // (TODO: add foreign merchants to destination)? +      // TODO: create SendUnits event with merchants back to source +    } +  } + +  public function dbInsert(): void +  { +    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) { +        /**@type Merchant $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, +          ] +        ); +      } +    } + +    // TODO: remove resources from source +  } + +  public function dbDelete(): void +  { +    DB::query('delete from events where id=:id', ['id' => $this->eventId]); +    DB::query('delete from events_send_resources where id=:id', ['id' => $this->id]); +    #DB::query('delete from events_send_resources_merchants where event_id=:id', ['id' => $this->id]); +  } +} diff --git a/src/Model/Event/SendResourcesMerchants.php b/src/Model/Event/SendResourcesMerchants.php new file mode 100644 index 0000000..a50b2bc --- /dev/null +++ b/src/Model/Event/SendResourcesMerchants.php @@ -0,0 +1,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]); +  } +} diff --git a/src/Model/Unit/Merchant.php b/src/Model/Unit/Merchant.php index 8958d27..be0b25e 100644 --- a/src/Model/Unit/Merchant.php +++ b/src/Model/Unit/Merchant.php @@ -3,6 +3,7 @@  namespace App\Model\Unit;  use App\Model\Unit; +use App\Model\Village;  class Merchant extends Unit  { @@ -22,4 +23,11 @@ class Merchant extends Unit      'iron' => 2.0,      'food' => 2.0,    ]; + +  public static function getResourceCapabilities(Village|int $village): int +  { +    $marketplace = Village::getBuilding($village->id ?? $village, 'Marketplace'); + +    return $marketplace->level * 100; +  }  } diff --git a/src/Model/Village.php b/src/Model/Village.php index c6709a6..019d9ba 100644 --- a/src/Model/Village.php +++ b/src/Model/Village.php @@ -3,6 +3,7 @@  namespace App\Model;  use App\DB; +use App\Model\Building\Marketplace;  use App\Model\Building\Storage;  use App\Model\Village\StorageConfig; @@ -53,6 +54,21 @@ class Village      return true;    } +  public static function canSendResources(Village $village): bool +  { +    $marketplace = Village::getBuilding($village->id, 'Marketplace'); +    if (! $marketplace) { +      return false; +    } + +    $merchants = Village::getUnit($village, $marketplace->unitType, Village::FETCH_UNIT_RESIDENCE, Village::RETURN_UNIT_EXISTING); +    if (! $merchants || $merchants->amount === 0) { +      return false; +    } + +    return true; +  } +    /* DB - Actions */    public static function get(int $id): ?Village @@ -136,8 +152,20 @@ class Village    public const RETURN_UNIT_ALL = 2;    public const RETURN_UNIT_TRAINABLE = 3; -  public static function getUnit(string $unitType, int $flag): ?Unit +  public static function getUnit(Village $village, string $unitType, int $fetchFlag = Village::FETCH_UNIT_RESIDENCE, int $returnFlag = Village::RETURN_UNIT_EXISTING): ?Unit    { +    if ($fetchFlag == Village::FETCH_UNIT_RESIDENCE) { +      $query = 'select * from village_units where residence_village_id=:id and type=:type and is_traveling=false'; +    } + +    $results = DB::fetch(Unit::class, $query, ['id' => $village->id, 'type' => $unitType]); +    if (isset($results[0])) { +      $unit = $results[0]->cast(); +    } else { +      return null; +    } + +    return $unit;    }    /** diff --git a/src/gemini/Controller/Village.php b/src/gemini/Controller/Village.php index 85b9205..70aa899 100644 --- a/src/gemini/Controller/Village.php +++ b/src/gemini/Controller/Village.php @@ -4,9 +4,13 @@ namespace App\gemini\Controller;  use App\DB;  use App\Guard; +use App\Model\Event; +use App\Model\Event\SendResources;  use App\Model\Event\SendUnits;  use App\Model\Event\TrainUnits;  use App\Model\Event\UpgradeBuilding; +use App\Model\Unit; +use App\Model\Unit\Merchant;  use App\Model\Village as Model;  use App\View;  use GeminiFoundation\Request; @@ -89,6 +93,26 @@ class Village        $events['SendUnits'][] = DB::convertToModel(SendUnits::class, $row);;      } +    $eventsResourcesSendOwn = DB::query( +      <<<SQL +      select * from events_send_resources as event +      left join events on event.event_id = events.id +      where village_id=:id +      SQL, ['id' => $village->id] +    )->fetchAll(); + +    $eventsResourcesSendOther = DB::query( +      <<<SQL +      select * from events_send_resources as event +      left join events on event.event_id = events.id +      where (destination=:id or source=:id) and village_id!=:id and is_canceled=false +      SQL, ['id' => $village->id] +    )->fetchAll(); + +    foreach ([...$eventsResourcesSendOwn, ...$eventsResourcesSendOther] as $row) { +      $events['SendResources'][] = DB::convertToModel(SendResources::class, $row);; +    } +      $buildings = [];      foreach (Model::getBuildings($village->id, true) as $building) {        $buildings[$building->type] = $building; @@ -100,6 +124,7 @@ class Village        'events' => $events,        'buildings' => $buildings,        'villages' => DB::fetch(Model::class, "select * from villages where id!=:id", ['id' => $village->id]), +      'marketplace' => $village->getBuilding($village->id, 'Marketplace'),      ]));    } @@ -164,4 +189,67 @@ class Village        meta: "/village/{$village->x}/{$village->y}/storage/config"      );    } + +  // #[Route(path: '/village/{x}/{y}/send-resources', methods: ['POST'])] +  public function sendResources(Request $request): Response +  { +    $village = Model::getByCoordinates($request->get('x'), $request->get('y')); + +    $selectedResourceType = $request->get('selectedResourceType'); +    if (empty($selectedResourceType)) { +      return new Response(body: View::render('send-resources/01-resource-types.twig', [ +        'village' => $village, +        'marketplace' => $village->getBuilding($village->id, 'Marketplace'), +      ])); +    } + +    if (empty($request->get('selectedVillageX'))) { +      return new Response(body: View::render('send-resources/02-villages.twig', [ +        'village' => $village, +        'villages' => DB::fetch(Model::class, "select * from villages where id!=:id", ['id' => $village->id]), +        'selectedResourceType' => $selectedResourceType, +        'marketplace' => $village->getBuilding($village->id, 'Marketplace'), +      ])); +    } +    $selectedVillage = Model::getByCoordinates($request->get('selectedVillageX'), $request->get('selectedVillageY')); + +    $amount = intval($request->get('input')); +    if (empty($amount)) { +      return new Response(statusCode: Status::INPUT, meta: 'Amount'); +    } + +    $resourceCapabilities = Merchant::getResourceCapabilities($village); +    $necessaryMerchants = ceil($amount / $resourceCapabilities); +    $merchants = DB::fetch(Merchant::class, 'select sum(amount) from village_units where type=:type and residence_village_id=:villageId and is_traveling=false', ['villageId' => $this->source, 'type' => 'Merchant'])[0]['amount'] ?? 0; +    if ($merchants === 0) { +      return new Response( +        statusCode: Status::REDIRECT_TEMPORARY, +        meta: "/village/{$village->x}/{$village->y}/type/$selectedResourceType/village/{$selectedVillage->x}/{$selectedVillage->y}" +      ); +    } + +    $destination = $selectedVillage; + +    // event +    $event = new Event(); +    $event->time = (new \DateTime())->add( +      \DateInterval::createFromDateString( +        Unit::getTravelTime(new Merchant(), Model::getDistance($village->x, $village->y, $destination->x, $destination->y)) +        . ' seconds' +      ) +    ); +    $event->villageId = $village->id; +    $sendResourcesEvent = new SendResources(); +    $sendResourcesEvent->event = $event; +    $sendResourcesEvent->$selectedResourceType = $amount; +    $sendResourcesEvent->source = $village->id; +    $sendResourcesEvent->destination = $destination->id; +    $sendResourcesEvent->dbInsert(); + + +    return new Response( +      statusCode: Status::REDIRECT_TEMPORARY, +      meta: "/village/{$village->x}/{$village->y}" +    ); +  }  } diff --git a/src/gemini/Gemini.php b/src/gemini/Gemini.php index 507b962..4c420d4 100644 --- a/src/gemini/Gemini.php +++ b/src/gemini/Gemini.php @@ -129,6 +129,25 @@ class Gemini          $response = $unitController->sendUnits($request);        } +      else if (preg_match('@village/(\d+)/(\d+)/send-resources@', $request->getPath(), $routeMatch)) { +        $request +          ->set('x', $routeMatch[1]) +          ->set('y', $routeMatch[2]); + +        if (preg_match('@village/(\d+)/(\d+)/send-resources/type/(\w+)$@', $request->getPath(), $routeMatch)) { +          $request->set('selectedResourceType', $routeMatch[3]); +        } +        else if (preg_match('@village/(\d+)/(\d+)/send-resources/type/(\w+)/village/(\d+)/(\d+)$@', $request->getPath(), $routeMatch)) { +          $request +            ->set('selectedResourceType', $routeMatch[3]) +            ->set('selectedVillageX', $routeMatch[4]) +            ->set('selectedVillageY', $routeMatch[5]); +        } + +        $villageController = new Village(); +        $response = $villageController->sendResources($request); +      } +        else if (preg_match('@village/(\d+)/(\d+)@', $request->getPath(), $routeMatch)) {          $request            ->set('x', $routeMatch[1]) diff --git a/views/gemini/send-resources/01-resource-types.twig b/views/gemini/send-resources/01-resource-types.twig new file mode 100644 index 0000000..586aa1e --- /dev/null +++ b/views/gemini/send-resources/01-resource-types.twig @@ -0,0 +1,4 @@ +Sendable Resource Capability: {{ marketplace.getResourceCapabilities(village) }} +{% for resourceType in ['wood', 'clay', 'iron', 'food'] %} +=> /village/{{ village.x }}/{{ village.y }}/send-resources/type/{{ resourceType }} {{ resourceType }} +{% endfor %} diff --git a/views/gemini/send-resources/02-villages.twig b/views/gemini/send-resources/02-villages.twig new file mode 100644 index 0000000..54ccc5c --- /dev/null +++ b/views/gemini/send-resources/02-villages.twig @@ -0,0 +1,6 @@ +{{ selectedResourceType }} +Sendable Resource Capability: {{ marketplace.getResourceCapabilities(village) }} + +{% for listVillage in villages %} +=> /village/{{ village.x }}/{{ village.y }}/send-resources/type/{{ selectedResourceType }}/village/{{ listVillage.x }}/{{ listVillage.y }} {{ listVillage.name }} - {{ listVillage.x }} x {{ listVillage.y }} +{% endfor %} diff --git a/views/gemini/send-units/02-villages.twig b/views/gemini/send-units/02-villages.twig index 80f5326..ea2741c 100644 --- a/views/gemini/send-units/02-villages.twig +++ b/views/gemini/send-units/02-villages.twig @@ -1,5 +1,5 @@  {{ selectedUnit }}  {% for listVillage in villages %} -=> /village/{{ village.x }}/{{ village.y }}/send-units/type/{{ selectedUnit }}/village/{{ listVillage.x }}/{{ listVillage.y }} {{ listVillage.name }} - {{ listVillage.x }} - {{ listVillage.y }} +=> /village/{{ village.x }}/{{ village.y }}/send-units/type/{{ selectedUnit }}/village/{{ listVillage.x }}/{{ listVillage.y }} {{ listVillage.name }} - {{ listVillage.x }} x {{ listVillage.y }}  {% endfor %} diff --git a/views/gemini/village.twig b/views/gemini/village.twig index d351eb6..d448020 100644 --- a/views/gemini/village.twig +++ b/views/gemini/village.twig @@ -57,6 +57,27 @@ Canceled  {% endfor %}  {% endif %} +{% if events['SendResources'] %} +## Send Resources +{% for event in events['SendResources'] %} +### {{ village.get(event.source).name }} -> {{ village.get(event.destination).name }} +Wood: {{ event.wood }} +Clay: {{ event.clay }} +Iron: {{ event.iron }} +Food: {{ event.food }} +Source: {{ village.get(event.source).name }} +Destination: {{ village.get(event.destination).name }} +Finished: {{ event.event.time | date('c') }} +{% if event.isCanceled %} +Canceled +{% else %} +{% if event.event.villageId == village.id %} +=> /event/{{ event.event.id }}/cancel Cancel +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +  # Buildings @@ -120,15 +141,11 @@ Travel Time: {{ unit.getTravelTime(unit, village.getDistance(unit.getHomeVillage  {% include 'send-units/01-units.twig' %} +{% if village.canSendResources(village) %}  # Send Resources -TODO -* list possible resource types -=> /village/{{ village.x }}/{{ village.y }}/send-resources/type/wood Wood -=> /village/{{ village.x }}/{{ village.y }}/send-resources/type/clay Clay -=> /village/{{ village.x }}/{{ village.y }}/send-resources/type/iron Iron -=> /village/{{ village.x }}/{{ village.y }}/send-resources/type/food Food -* list possible villages -* send INPUT request for amount +{% include 'send-resources/01-resource-types.twig' %} +{% endif %} +  {% include 'footer.twig' %} | 
