Something went wrong. Try again.
Perl game server for TLE Community
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532use 5.010;use strict;use lib '/home/lacuna/server/lib';use Lacuna::DB;use Lacuna;use Lacuna::Util qw(format_date);use Getopt::Long;use JSON;use Lacuna::Constants qw(SHIP_TYPES ORE_TYPES);use utf8;
$|=1;
our $quiet;
GetOptions( 'quiet' => \$quiet, );
out('Started'); my $start = DateTime->now;
out('Loading DB'); our $db = Lacuna->db;
summarize_colonies(); my $mapping = summarize_empires(); summarize_alliances(); delete_old_records($start); rank_colonies(); rank_empires(); rank_alliances(); output_map($mapping); generate_overview();
my $finish = time; out('Finished'); out((($finish - $start->epoch)/60)." minutes have elapsed");exit;
################# SUBROUTINES###############
sub generate_overview { out('Generating Overview'); my $stars = $db->resultset('Map::Star'); my $bodies = $db->resultset('Map::Body'); my @off_limits = $bodies->search({empire_id => {'<' => 2}})->get_column('id')->all; my $ships = $db->resultset('Ships')->search({body_id => { 'not in' => \@off_limits}}); my $glyphs = $db->resultset('Glyph')->search({body_id => { 'not in' => \@off_limits}}); my $buildings = $db->resultset('Building')->search({body_id => { 'not in' => \@off_limits}}); my $empires = $db->resultset('Empire')->search({id => { '>' => 1}}); # Get all probes, either observatory or oracle my $probes = $db->resultset('Probes')->search({empire_id => { '>' => 1} }); my $dtformatter = $db->storage->datetime_parser; # basics out('Getting Basic Counts'); my %out = ( stars => { count => $stars->count, # number of probes (observatory) probes_count => $probes->search({virtual => 0})->count, # number of probed stars (either observatory or oracle) probed_count => $probes->search(undef, { group_by => ['star_id'] })->count, seized_count => $stars->search({station_id => { '!=' => 'Null' }})->count, }, bodies => { count => $bodies->count, colony_count => $bodies->search({empire_id => { '>' => 0}})->count, }, ships => { count => $ships->count, }, buildings => { count => $buildings->count, }, empires => { count => $empires->count, average_university_level => $empires->get_column('university_level')->func('avg'), highest_university_level => $empires->get_column('university_level')->max, isolationist_count => $empires->search({is_isolationist => 1})->count, essentia_using_count => $empires->search([map { $_ => { '>' => 0 } } qw(essentia_free essentia_paid essentia_game)])->count, currently_active_count => $empires->search({last_login => {'>=' => $dtformatter->format_datetime(DateTime->now->subtract(hours=>1))}})->count, active_today_count => $empires->search({last_login => {'>=' => $dtformatter->format_datetime(DateTime->now->subtract(hours=>24))}})->count, active_this_week_count => $empires->search({last_login => {'>=' => $dtformatter->format_datetime(DateTime->now->subtract(days=>7))}})->count, }, ); # flesh out bodies out('Flesh Out Body Stats'); my %body_types = ( gas_giants => 'Lacuna::DB::Result::Map::Body::Planet::GasGiant%', habitables => 'Lacuna::DB::Result::Map::Body::Planet::P%', stations => 'Lacuna::DB::Result::Map::Body::Planet::Station', asteroids => 'Lacuna::DB::Result::Map::Body::Asteroid%', ); foreach my $key (keys %body_types) { out($key); my $type = $bodies->search({class => {like => $body_types{$key}}}); $out{bodies}{types}{$key} = { count => $type->count, average_size => $type->get_column('size')->func('avg'), largest_size => $type->get_column('size')->max, smallest_size => $type->get_column('size')->min, average_orbit => $type->get_column('orbit')->func('avg'), }; }
# flesh out orbits out('Flesh Out Orbital Stats'); foreach my $orbit (1..8) { out($orbit); $out{orbits}{$orbit} = { inhabited => $bodies->search({empire_id => {'>', 0}, orbit => $orbit})->count, bodies => $bodies->search({orbit => $orbit})->count, } }
# flesh out buildings out('Flesh Out Building Stats'); my $distinct = $buildings->search(undef, { group_by => ['class'] })->get_column('class'); while (my $class = $distinct->next) { out($class); my $type_rs = $buildings->search({class=>$class}); my $count = $type_rs->count; $out{buildings}{types}{$class->name} = { average_level => $type_rs->get_column('level')->func('avg'), highest_level => $type_rs->get_column('level')->max, count => $count, }; }
# flesh out ships out('Flesh Out Ship Stats'); foreach my $type (SHIP_TYPES) { my $type_rs = $ships->search({type=>$type}); my $count = $type_rs->count; $out{ships}{types}{$type} = { average_hold_size => $type_rs->get_column('hold_size')->func('avg'), largest_hold_size => $type_rs->get_column('hold_size')->max, smallest_hold_size => $type_rs->get_column('hold_size')->min, average_speed => $type_rs->get_column('speed')->func('avg'), fastest_speed => $type_rs->get_column('speed')->max, slowest_speed => $type_rs->get_column('speed')->min, count => $count }; }
# flesh out glyphs out('Flesh Out Glyphs Stats'); my $glyph_rs = $glyphs->search(undef, { group_by => 'type', select => [ 'type', { sum => 'quantity' }, ], as => [qw(type quantity)], }); while (my $glyph = $glyph_rs->next) { $out{glyphs}{types}{$glyph->type} = $glyph->quantity; }
if (-e '/home/lacuna/server/public/server/server_overview.json') { open my $read, '<', '/home/lacuna/server/public/server/server_overview.json' or die "Couldn't read server_overview.json: $!"; my $old_stats = from_json(do { local $/; <$read> }); $out{spies} = $old_stats->{spies}; }
open my $fh, '>', '/home/lacuna/server/public/server/server_overview.json' or die "Couldn't write server_overview.json: $!"; print $fh to_json(\%out); close $fh;}
sub rank_colonies { out('Ranking Colonies'); my $colonies = $db->resultset('Log::Colony'); foreach my $field (qw(population)) { my $ranked = $colonies->search(undef, {order_by => [ {-desc => $field}, 'rand()']}); my $counter = 1; while (my $colony = $ranked->next) { $colony->update({$field.'_rank' => $counter++}); } }}
sub rank_empires { out('Ranking Empires'); my $empires = $db->resultset('Log::Empire'); foreach my $field (qw(empire_size university_level offense_success_rate defense_success_rate dirtiest)) { my $ranked = $empires->search(undef, {order_by => [ {-desc => $field}, 'rand()']}); my $counter = 1; while (my $empire = $ranked->next) { $empire->update({$field.'_rank' => $counter++}); } }}
sub rank_alliances { out('Ranking Alliances'); my $alliances = $db->resultset('Log::Alliance'); foreach my $field (qw(influence population space_station_count average_empire_size offense_success_rate defense_success_rate dirtiest)) { my $ranked = $alliances->search(undef, {order_by => [{-desc => $field},'rand()']}); my $counter = 1; while (my $alliance = $ranked->next) { $alliance->update({$field.'_rank' => $counter++}); } }}
sub delete_old_records { out('Deleting old records'); my $start = shift; $db->resultset('Log::Alliance')->search({date_stamp => { '<' => $start}})->delete; $db->resultset('Log::Empire')->search({date_stamp => { '<' => $start}})->delete; $db->resultset('Log::Colony')->search({date_stamp => { '<' => $start}})->delete;}
sub summarize_alliances { out('Summarizing Alliances'); my $logs = $db->resultset('Log::Alliance'); my $alliances = $db->resultset('Alliance'); my $empire_logs = $db->resultset('Log::Empire'); while (my $alliance = $alliances->next) { next if ! defined $alliance->leader_id; # until Alliances get deleted... out($alliance->name); my %alliance_data = ( date_stamp => DateTime->now, space_station_count => 0, influence => 0, alliance_id => $alliance->id, alliance_name => $alliance->name, ); my $empires = $empire_logs->search({alliance_id => $alliance->id}); while ( my $empire = $empires->next) { $alliance_data{member_count}++; $alliance_data{colony_count} += $empire->colony_count; $alliance_data{space_station_count} += $empire->space_station_count; $alliance_data{influence} += $empire->influence; $alliance_data{population} += $empire->population; $alliance_data{building_count} += $empire->building_count; $alliance_data{average_building_level} += $empire->average_building_level; $alliance_data{defense_success_rate} += $empire->defense_success_rate; $alliance_data{offense_success_rate} += $empire->offense_success_rate; $alliance_data{dirtiest} += $empire->dirtiest; $alliance_data{spy_count} += $empire->spy_count; $alliance_data{average_empire_size} += $empire->empire_size; $alliance_data{average_university_level} += $empire->university_level; } if ($alliance_data{member_count}) { $alliance_data{average_empire_size} /= $alliance_data{member_count}; $alliance_data{average_university_level}/= $alliance_data{member_count}; $alliance_data{average_building_level} /= $alliance_data{member_count}; $alliance_data{offense_success_rate} /= $alliance_data{member_count}; $alliance_data{defense_success_rate} /= $alliance_data{member_count}; } my $log = $logs->search({alliance_id => $alliance->id})->first; if (defined $log) { if ($alliance_data{member_count}) { $log->update(\%alliance_data); } else { $log->delete; } } else { $logs->new(\%alliance_data)->insert; } }}
sub summarize_empires { out('Summarizing Empires'); my $logs = $db->resultset('Log::Empire'); my $empires = $db->resultset('Empire')->search({ id => {'>' => 1} }); my $colony_logs = $db->resultset('Log::Colony'); my %mapping; while (my $empire = $empires->next) { out($empire->name); my %empire_data = ( date_stamp => DateTime->now, university_level => $empire->university_level, empire_id => $empire->id, empire_name => $empire->name, alliance_id => $empire->alliance_id, space_station_count => 0, influence => 0, ); my %map_data = ( empire_id => $empire->id, empire_name => $empire->name, alliance_id => $empire->alliance_id, home_id => $empire->home_planet_id, ); if ($empire->alliance_id) { $empire_data{alliance_name} = $empire->alliance->name; $map_data{alliance_name} = $empire->alliance->name; } else { $empire_data{alliance_name} = undef; $map_data{alliance_id} = 0; $map_data{alliance_name} = "Neutral"; } my @map_colonies; my $colonies = $colony_logs->search({empire_id => $empire->id}); while ( my $colony = $colonies->next) { if ($colony->is_space_station) { $empire_data{influence} += $colony->influence; $empire_data{space_station_count}++; my %map_col = ( type => "SS", x => $colony->x, y => $colony->y, zone => $colony->zone, name => "", ); push @map_colonies, \%map_col; } else { $empire_data{colony_count}++; $empire_data{population} += $colony->population; $empire_data{population_delta} += $colony->population_delta; $empire_data{building_count} += $colony->building_count; $empire_data{average_building_level} += $colony->average_building_level; $empire_data{highest_building_level} = $colony->highest_building_level if ($colony->highest_building_level > $empire_data{highest_building_level}); $empire_data{food_hour} += $colony->food_hour; $empire_data{ore_hour} += $colony->ore_hour; $empire_data{energy_hour} += $colony->energy_hour; $empire_data{water_hour} += $colony->water_hour; $empire_data{waste_hour} += $colony->waste_hour; $empire_data{happiness_hour} += $colony->happiness_hour; $empire_data{defense_success_rate} += $colony->defense_success_rate; $empire_data{defense_success_rate_delta}+= $colony->defense_success_rate_delta; $empire_data{offense_success_rate} += $colony->offense_success_rate; $empire_data{offense_success_rate_delta}+= $colony->offense_success_rate_delta; $empire_data{dirtiest} += $colony->dirtiest; $empire_data{dirtiest_delta} += $colony->dirtiest_delta; $empire_data{spy_count} += $colony->spy_count; if ($colony->body_id eq $map_data{home_id}) { my %map_col = ( type => "Cap", x => $colony->x, y => $colony->y, zone => $colony->zone, name => "", ); push @map_colonies, \%map_col; } } } if (scalar @map_colonies > 0) { $map_data{bodies} = \@map_colonies; %{$mapping{$map_data{empire_id}}} = %map_data; } if ($empire_data{colony_count}) { $empire_data{average_building_level} = $empire_data{average_building_level} / $empire_data{colony_count}; $empire_data{offense_success_rate} = $empire_data{offense_success_rate} / $empire_data{colony_count}; $empire_data{defense_success_rate} = $empire_data{defense_success_rate} / $empire_data{colony_count}; } $empire_data{empire_size} = $empire_data{colony_count} * $empire_data{population}; my $log = $logs->search({empire_id => $empire->id})->first; if (defined $log) { $empire_data{colony_count_delta} = $empire_data{colony_count} - $log->colony_count + $log->colony_count_delta; $empire_data{empire_size_delta} = ($empire_data{colony_count_delta}) ? $empire_data{colony_count_delta} * $empire_data{population_delta} : $empire_data{population_delta}; $log->update(\%empire_data); } else { $logs->new(\%empire_data)->insert; } } my $ai = $db->resultset('Empire')->search({ id => {'<' => 0} }); out('Summarizing AI for map'); while (my $empire = $ai->next) { my %map_data = ( empire_id => $empire->id, empire_name => $empire->name, alliance_id => $empire->id, alliance_name => $empire->name, home_id => $empire->home_planet_id, ); my @map_colonies; my $colonies = $db->resultset('Map::Body')->search({ empire_id => $empire->id}); while ( my $colony = $colonies->next) { my %map_col = ( x => $colony->x, y => $colony->y, zone => $colony->zone, name => $colony->name, ); my $btype = $colony->get_type; if ($btype eq "space staion") { $map_col{type} = "SS", } elsif ($colony->id == $map_data{home_id}) { $map_col{type} = "Cap", } else { $map_col{type} = "Col", } push @map_colonies, \%map_col; } if (scalar @map_colonies > 0) { $map_data{bodies} = \@map_colonies; %{$mapping{$map_data{empire_id}}} = %map_data; } } return (\%mapping);}
sub summarize_colonies { out('Summarizing Planets'); my $logs = $db->resultset('Log::Colony'); my $planets = $db->resultset('Map::Body')->search({ empire_id => {'>' => 1} },{order_by => 'name'}); my $spy_logs = $db->resultset('Log::Spies'); while (my $planet = $planets->next) { out($planet->name); my $log = $logs->search({planet_id => $planet->id})->first; my %colony_data = ( date_stamp => DateTime->now, planet_name => $planet->name, building_count => scalar @{ $planet->building_cache }, population => $planet->population, population_delta => (defined $log ? $log->population_delta + $planet->population - $log->population : $planet->population ), average_building_level => $planet->building_avg_level, highest_building_level => $planet->building_max_level, food_hour => $planet->food_hour, water_hour => $planet->water_hour, waste_hour => $planet->waste_hour, energy_hour => $planet->energy_hour, ore_hour => $planet->ore_hour, happiness_hour => $planet->happiness_hour, empire_id => $planet->empire_id, empire_name => $planet->empire->name, body_id => $planet->id, x => $planet->x, y => $planet->y, zone => $planet->zone, ); if ($planet->class =~ /Station$/) { $colony_data{is_space_station} = 1; $colony_data{influence} = $planet->influence_spent; }
my $spies = $spy_logs->search({planet_id => $planet->id}); while (my $spy = $spies->next) { $colony_data{spy_count}++; $colony_data{offense_success_rate} += $spy->offense_success_rate; $colony_data{offense_success_rate_delta} += $spy->offense_success_rate_delta; $colony_data{defense_success_rate} += $spy->defense_success_rate; $colony_data{defense_success_rate_delta} += $spy->defense_success_rate_delta; $colony_data{dirtiest} += $spy->dirtiest; $colony_data{dirtiest_delta} += $spy->dirtiest_delta; } $colony_data{offense_success_rate} = ($colony_data{spy_count}) ? $colony_data{offense_success_rate} / $colony_data{spy_count} : 0; $colony_data{defense_success_rate} = ($colony_data{spy_count}) ? $colony_data{defense_success_rate} / $colony_data{spy_count} : 0; if (defined $log) { $log->update(\%colony_data); } else { $colony_data{planet_id} = $planet->id; $logs->new(\%colony_data)->insert; } }}
sub output_map { my $mapping = shift; # my $map_txt = JSON->new->utf8->encode($mapping);# open(OUT, ">:utf8:", "mapping.json");# print OUT $map_txt;# close(OUT); my %output; my $star_map_size = Lacuna->config->get('map_size'); $output{map} = { bounds => $star_map_size, }; for my $emp_id (keys %$mapping) { my @info; my @data; for my $bod (@{$mapping->{$emp_id}->{bodies}}) { my $info_str = sprintf("%s (%s) -- %s : (%d,%d) [%s]", ($bod->{name} ne "") ? $bod->{name} : $mapping->{$emp_id}->{empire_name}, $mapping->{$emp_id}->{alliance_name}, $bod->{type}, $bod->{x}, $bod->{y}, $bod->{zone}); my $data_str = [ $bod->{x}, $bod->{y} ]; push @info, $info_str; push @data, $data_str; } my $key = $mapping->{$emp_id}->{alliance_id}; if (defined $output{alliances}->{$key}) { push @{$output{alliances}->{$key}->{info}}, @info; push @{$output{alliances}->{$key}->{data}}, @data; } else { $output{alliances}->{$key}->{label} = $mapping->{$emp_id}->{alliance_name}; $output{alliances}->{$key}->{alliance_id} = $mapping->{$emp_id}->{alliance_id}; $output{alliances}->{$key}->{info} = \@info; $output{alliances}->{$key}->{data} = \@data; } } my $json_txt = JSON->new->utf8->encode(\%output);
open my $fh, '>', '/home/lacuna/server/public/server/starmap.json'; print $fh $json_txt; close $fh;}
# UTILITIES
sub out { my $message = shift; unless ($quiet) { say format_date(DateTime->now), " ", $message; }}