Skip to content

Instantly share code, notes, and snippets.

@marhei
Last active September 1, 2022 16:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marhei/c264e204105ffe15bb211b561f15dce4 to your computer and use it in GitHub Desktop.
Save marhei/c264e204105ffe15bb211b561f15dce4 to your computer and use it in GitHub Desktop.
Ermittlung der besten Bewerbung für eine Ausschreibung
<?php
/**
* TrainCompany - Criteria.enum.php
*
* @author Marcel Heisinger
*/
namespace Game\Task\Application;
use Game\Task\{Application, Schedule};
enum Criteria {
case Time; // Fahrzeiten (unrealistische Fahrzeiten werden nicht berücksichtigt)
case Capacity; // Kapazität
case Drive; // Antrieb
case Kilometers; // Kilometer des Users
case Service; // Das Service-Level des Auftrags und der Fahrzeuge
/**
* Zieht den Wert für das jeweilige Kriterium aus der Ausschreibung
*
* @param Application $application description
*
* @return int description
*/
public function getValue(Application $app): ?int {
return match($this) {
static::Time => max($app->schedule->getFullTime()->toInt(), Schedule::fromApplication($app)->getFullTime()->toInt()),
static::Capacity => $app->trainUnit->getFullCapacity(array_keys($app->task->neededCapacity)),
static::Drive => $app->trainUnit->getDrive()->getFactor($app->pathUnit->electrified),
static::Kilometers => $app->user->getKilometers(),
static::Service => $app->task->service->preferMatchingTrain() ? $app->trainUnit->getService()?->value : NULL,
};
}
/**
* Gibt die Gewichtung der verschiedenen Kriterien zurück
*
* @return int
*/
public function getWeighting(): int {
return match($this) {
static::Capacity => 3,
static::Service,
static::Time => 2,
default => 1
};
}
/**
* Sortiert die Arrays in der richtigen Reihenfolge
*
* @param array $array
*
* @return void
*/
public function sort(array &$array): void {
match($this) {
static::Time,
static::Service,
static::Kilometers => asort($array),
static::Capacity,
static::Drive => arsort($array)
};
}
}
?>
<?php
/**
* TrainCompany - Drive.enum.php
* Antrieb des Fahrzeuges
*
* @author Marcel Heisinger
*/
namespace Game\Train;
use Game\Path\Unit;
enum Drive: int {
use \Core\Enum;
case Without = 0;
case Electro = 1;
case Diesel = 2;
case Battery = 3;
case DualMode = 4;
case Hydrogen = 5;
case LastMile = 6;
case Steam = 7;
/** -- verkürzt -- **/
/**
* Gibt den Faktor bei der Bewerbungsauswahl zurück
*
* @param bool $electrified
*
* @return float
*/
public function getFactor(bool $electrified): int {
return match($this) {
static::Electro => 10,
static::Battery => $electrified ? 9 : 10,
static::LastMile,
static::DualMode => $electrified ? 8 : 10,
static::Diesel => $electrified ? 7 : 8,
static::Hydrogen => $electrified ? 8 : 10,
static::Steam => 5,
default => 0,
};
}
/** -- verkürzt -- **/
}
?>
<?php
/**
* TrainCompany - Service.enum.php
* Servicelevel einer Ausschreibung
*
* @author Marcel Heisinger
*/
namespace Game\Task;
enum Service: int {
case Highspeed = 0;
case Intercity = 1;
case Regional = 2;
case ShortRegional = 3;
case Special = 4;
case FreightImportant = 10;
case Freight = 11;
/**
* Gibt den Namen des Service zurück
*
* @return string
*/
public function getName(): string {
return match($this) {
static::Highspeed => 'HGV',
static::Intercity => 'IC',
static::Regional => 'RE/RB',
static::ShortRegional => 'S-Bahn',
static::Special => 'Sonderzug',
static::FreightImportant=> 'hochwertiger GV',
static::Freight => 'GV',
};
}
/**
* Gibt den Faktor zur Preiserstellung zurück
*
* @return float
*/
public function getFactor(): float {
return match($this) {
static::FreightImportant => 1.3,
static::Highspeed, static::Freight => 1.2,
static::Intercity, static::Special => 1.1,
static::Regional, static::ShortRegional => 1.5,
};
}
/**
* Gibt an wie lange eine DV angeboten wird
*
* @return int
*/
public function getEndTime(): int {
return match($this) {
static::FreightImportant, static::Freight => 3600,
default => 1200
};
}
/**
* Gibt an ob für diesen Service passende Fahrzeuge bevorzugt werden sollen.
*
* @return bool
*/
public function preferMatchingTrain(): bool {
return match($this) {
static::Highspeed,
static::Intercity => true,
default => false
};
}
}
?>
<?php
/**
* TrainCompany - Task.class.php
*
* @author Marcel Heisinger
*/
namespace Game;
use Game\{Train\Drive, Path\Unit, Train\Unit\Weight};
use Game\Task\{Journey, Difficulty, Type, Service, Application,
Application\Manager as ApplicationManager,
Journey\Manager as JourneyManager
};
use Core\{Format, Time\Duration};
class Task implements \Core\Access\Accessable, \Core\Manager\Managable {
use Station\Tools, \Core\Access;
/** -- verkürzt -- **/
/**
* Gibt die beste Bewerbung für diese Ausschreibung zurück
*
* @return ?Application
*/
public function getBestApplication(): ?Application {
// Bei Direktvergaben gibt es keine beste Ausschreibung
if($this->type->isDirect()) return NULL;
// Nur abgeschlossene Bewerbungen berücksichtigen
$applications = array_filter(ApplicationManager::iFor($this->id)->toArray(true), fn(Application $a): bool => $a->finished);
// Keine abgeschlossene Bewerbungen?
if(!count($applications)) return NULL;
// Array zufällig sortieren um frühere Bewerbungen nicht zu bevorteilen
shuffle($applications);
// Bewerbungen sortieren
usort($applications, function(Application $a, Application $b): int {
// Kriterien durchgehen
$values = [];
foreach(Application\Criteria::cases() as $criteria) {
[$av, $bv] = $value = array_map(fn(Application $a): ?int => $criteria->getValue($a), [$a, $b]);
// Wenn gleiches Value, dann Kriterium ignorieren
if($av == $bv) continue;
// Null rauslöschen
$value = array_filter($value, fn($v): bool => !is_null($v));
// Sortieren und Gewinner hinzufügen
$criteria->sort($value);
for($i=0;$i<$criteria->getWeighting();$i++) $values[] = array_key_first($value);
}
// Wer hat den ersten Platz?
$keys = array_count_values($values);
return ($keys[1] ?? 0) <=> ($keys[0] ?? 0);
});
// Platz 1 zurückgeben
return $applications[array_key_first($applications)];
}
/** -- verkürzt -- **/
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment