Skip to content

Instantly share code, notes, and snippets.

@nrctkno
Created December 28, 2021 19:57
Show Gist options
  • Save nrctkno/b8932941cb98d1814d6ccd3307c576a2 to your computer and use it in GitHub Desktop.
Save nrctkno/b8932941cb98d1814d6ccd3307c576a2 to your computer and use it in GitHub Desktop.
<?php
class Random
{
public static function distributed($elements)
{
if (array_sum($elements) !== 100) {
throw new \Exception('randomWithDistribution: sum of probabilities must be 100');
}
$random = rand(1, 100);
$tot = 0;
foreach ($elements as $id => $weight) {
$tot += $weight;
if ($random <= $tot) {
return $id;
}
}
}
}
abstract class RandomType
{
protected array $settings;
function __construct(array $settings)
{
$this->settings = $settings;
}
abstract function craft(array $record);
}
class FallbackType extends RandomType
{
public function craft(array $record)
{
return $this->settings['name'] . ' is not implemented';
}
}
class RangeType extends RandomType
{
public function craft(array $record)
{
$min = $this->settings[1][0];
$max = $this->settings[1][1];
return rand($min, $max);
}
}
class OptionType extends RandomType
{
public function craft(array $record)
{
$entries = $this->settings[1];
return $entries[mt_rand(0, count($entries) - 1)];
}
}
class WeightedOptionType extends RandomType
{
public function craft(array $record)
{
return Random::distributed($this->settings[1]);
}
}
class DateType extends RandomType
{
public function craft(array $record)
{
$min = strtotime($this->settings[1][0]);
$max = strtotime($this->settings[1][1]);
$time = mt_rand($min, $max);
return (new \DateTime())->setTimestamp($time);
}
}
class CustomType extends RandomType
{
public function craft(array $record)
{
$closure = $this->settings[1];
return $closure($record);
}
}
class Seeder
{
public static function seed(int $qty, array $rules, Closure $onGenerated): void
{
$generators = self::getGenerators($rules);
for ($i = 1; $i <= $qty; $i++) {
$record = ['__id__' => $i];
foreach ($generators as $field => $g) {
$record[$field] = $g->craft($record);
}
$onGenerated($record);
}
}
private static function getGenerators(array $rules): array
{
$generators = [];
foreach ($rules as $field => $rule) {
$generators[$field] = self::instantiateGenerator($rule);
}
return $generators;
}
private static function instantiateGenerator(array $rule): RandomType
{
$generatorName = ucfirst($rule[0]) . 'Type';
if (!class_exists($generatorName)) {
return new FallbackType(['name' => $rule[0]]);
}
return new $generatorName($rule);
}
}
/*
Usage
*/
$output_file = fopen('output.sql', 'w');
Seeder::seed(40000, [
'status' => ['option', ['a']],
'cycle' => ['WeightedOption', ['d' => 97, 'm' => 3]],
'grouping' => ['range', [0, 2]],
'fiscal_id' => ['range', [1, 2000]],
'start' => ['date', ['2021-01-01 00:00:00', '2021-12-31 00:00:00']],
'end' => ['custom', function ($record) {
$end = clone $record['start'];
return $end->modify($record['cycle'] == 'm' ? '+ 1 month' : '+ 1 day');
}],
], function (array $record) use($output_file) {
$query ='insert into myTable (status, cycle, grouping, fiscal_id, start, end) values '
. sprintf(
"('%s', '%s', %d, %d, '%s', '%s');\r\n",
$record['status'],
$record['cycle'],
$record['grouping'],
$record['fiscal_id'],
$record['start']->format('Y-m-d'),
$record['end']->format('Y-m-d')
);
//echo $query . "<br />";
fwrite($output_file, $query);
});
fclose($output_file);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment