From 7cb988dd6a42a849b25e6304b307ab221a2b0c8d Mon Sep 17 00:00:00 2001 From: Ajick Date: Fri, 9 Jun 2023 18:38:31 +0500 Subject: [PATCH] feat: Add calculation of statistics data by categories. Add /top console command. Refactor and fix Statistics module. --- info.json | 2 +- locale/en/strings.cfg | 45 ++- locale/ru/strings.cfg | 43 +++ scripts/statistics.lua | 673 +++++++++++++++++++++++++++++++++-------- 4 files changed, 632 insertions(+), 131 deletions(-) diff --git a/info.json b/info.json index 8d96e03..457e126 100644 --- a/info.json +++ b/info.json @@ -1,6 +1,6 @@ { "name": "Fed1sServerMod", - "version": "1.0.30", + "version": "1.1.0", "title": "Fed1sServerMod", "author": "danbka33", "contact": "", diff --git a/locale/en/strings.cfg b/locale/en/strings.cfg index 31480ff..5af157d 100644 --- a/locale/en/strings.cfg +++ b/locale/en/strings.cfg @@ -98,7 +98,50 @@ tooltip-promote=Make a manager tooltip-unban=Unban tooltip-unfavorite=Remove from Favorites tooltip-unmute=Unmute -tooltip-warn=Warn the player +tooltip-warn=Warn + +[statistics] +heading-1=[font=heading-1]__1__[/font] +heading-3=[font=heading-3]__1__[/font] +all-categories=All catogories +wrong-parameter=Wrong parameter! +no-data=No data for this category. +builders=Top Builders +builders-info=The amount of hand-built objects. +architectors=Top Architectors +architectors-info=The amount of installed ghosts. +military_enginears=Top Military enginears +military_enginears-info=The amount of turrets and walls installed, including their ghosts. +crafters=Top Crafters +crafters-info=The amount of crafted items. +repairemans=Top Repairemans +repairemans-info=The amount of repared health points of objects. +wariors=Top Wariors +wariors-info=The amount of killed biters. +tree_haters=Top Tree haters +tree_haters-info=The amount of destroyed trees. +rock_haters=Top Rock haters +rock_haters-info=The amount of destroyed rocks. +miners=Top Miners +miners-info=The amount of mined ore, stones and coal. +deaths=Top Deaths +deaths-info=The amount of deaths. +railwaymans=Top Railwaymans +railwaymans-info=The amount of installed railroad type of items. +runners=Top Runners +runners-info=The amount of traveled distance. +lumberjacks=Top Lumberjacks +lumberjacks-info=The amount of cuted trees. +mariobrothers=Top Plumbers +mariobrothers-info=The amount of installed pipes. +oilmans=Top Oilmans +oilmans-info=The amount of installed oil-processing items. +roadworkers=Top Roadworkers +roadworkers-info=The amount of installed path and landfill tiles. +electricians=Top Electricians +electricians-info=The amount of installet electic poles. +fishermans=Top Fishermans +fishermans-info=The amount of fish caught. [entity-name] yellow-chest=Party Request Resource Chest diff --git a/locale/ru/strings.cfg b/locale/ru/strings.cfg index 7e97b2f..49d11ef 100644 --- a/locale/ru/strings.cfg +++ b/locale/ru/strings.cfg @@ -100,6 +100,49 @@ tooltip-unfavorite=Удалить из Избранных tooltip-unmute=Разрешить писать сообщения tooltip-warn=Вынести предупреждение +[statistics] +heading-1=[font=heading-1]__1__[/font] +heading-3=[font=heading-3]__1__[/font] +all-categories=Все категории +wrong-parameter=Задан некорректный параметр. +no-data=Пока нет статистических данных для этой категории. +builders=Топ Строителей +builders-info=Количество построенных руками объектов. +architectors=Топ Архитекторов +architectors-info=Количество установленных призраков. +military_enginears=Топ Военных инженеров +military_enginears-info=Количество установленных турелей и стен, включая их призраки. +crafters=Топ Крафтеров +crafters-info=Количество скрафченных в кармане предметов. +repairemans=Топ Ремонтников +repairemans-info=Количество восстановленных очков здоровья у объектов. +wariors=Топ войнов +wariors-info=Количество убитых местных жителей. +tree_haters=Топ Ненавистников деревьев +tree_haters-info=Количество убитых деревьев. +rock_haters=Топ Ненавистников камней +rock_haters-info=Количество убитых камней. +miners=Топ Шахтёров +miners-info=Количество добытых киркой камней и угля и руды всех видов. +deaths=Топ Смертников +deaths-info=Количество смертей. +railwaymans=Топ Железнодорожников +railwaymans-info=Количество установленных железнодорожных объектов, включая их призраки. +runners=Топ Бегунов +runners-info=Количество пройденных игроком клеток. +lumberjacks=Топ Лесорубов +lumberjacks-info=Количество срубренных деревьев. +mariobrothers=Топ Водопроводчиков +mariobrothers-info=Количество установленных вручную труб. +oilmans=Топ Нефтянников +oilmans-info=Количество установленных объектов, относящихся к нефтепереработке, а так же труб и цистерн. +roadworkers=Топ Дорожнных рабочих +roadworkers-info=Количество проложенных вручную дорожек и отсыпки. +electricians=Топ Электриков +electricians-info=Количество уставновленных не столбов, а опор. +fishermans=Топ Рыбаков +fishermans-info=Количество выловленной рыбы. + [entity-name] yellow-chest=Сундук запроса ресурсов на нужды партии blue-chest2=Сундук запроса ресурсов из оффлайна diff --git a/scripts/statistics.lua b/scripts/statistics.lua index 15203f9..a28872e 100755 --- a/scripts/statistics.lua +++ b/scripts/statistics.lua @@ -4,122 +4,458 @@ local Statistics = {} Statistics.counter = 1 -Statistics.types = { - builded = "builded", - killed = "killed", - deaths = "deaths", - repaired = "repaired", - mined = "mined", - crafted = "crafted", - walked = "walked" +Statistics.type_names = { + "builded", + "killed", + "deaths", + "repaired", + "mined", + "crafted", + "walked" } - -Statistics.tops = { - builders = "builders", - architectors = "architectors", - war_enginears = "war_enginears", - crafters = "crafters", - repairemans = "repairemans", - wariors = "wariors", - tree_haters = "tree_haters", - rock_haters = "rock_haters", - miners = "miners", - sueciders = "sueciders", - railwaymans = "railwaymans", - runners = "runners", - lumberjacks = "lumberjacks", - mariobrothers = "mariobrothers" +Statistics.types = {} +for _, type_name in pairs(Statistics.type_names) do + Statistics.types[type_name] = type_name +end + +Statistics.top_names = { + "builders", + "architectors", + "military_enginears", + "crafters", + "repairemans", + "wariors", + "tree_haters", + "rock_haters", + "miners", + "deaths", + "railwaymans", + "runners", + "lumberjacks", + "mariobrothers", + "oilmans", + "roadworkers", + "electricians", + "fishermans" } - -- "oilmans", +Statistics.tops = {} +for _, top_name in pairs(Statistics.top_names) do + Statistics.tops[top_name] = top_name +end -- Statistics calculation functions -- -function Statistics.calculate_builders() -- NotImplemented +function Statistics.calculate_builders() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + for player_index, items in pairs(builded) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if item_name ~= "ghosts" then + record.count = record.count + count + end + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.builders) end -function Statistics.calculate_architectors() -- NotImplemented +function Statistics.calculate_architectors() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + for player_index, items in pairs(builded) do + if not items.ghosts then + goto continue + end + + local record = {player_index=player_index, count=0} + + for _, count in pairs(items.ghosts) do + record.count = record.count + count + end + + table.insert(top, record) + + ::continue:: + end + + Statistics.sort_and_set_top(top, Statistics.tops.architectors) end -function Statistics.calculate_war_enginears() -- NotImplemented - -- body +function Statistics.calculate_military_enginears() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + local function calculate(items) + local total_count = 0 + + for item_name, count in pairs(items) do + if Statistics.is_defensive_stuff(item_name) then + total_count = total_count + count + elseif item_name == "ghosts" then + total_count = total_count + calculate(count) + end + end + + return total_count + end + + for player_index, items in pairs(builded) do + local record = {player_index=player_index, count=calculate(items)} + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.military_enginears) end -function Statistics.calculate_crafters() -- NotImplemented +function Statistics.calculate_crafters() + local crafted = Statistics.get_raw_data_type(Statistics.types.crafted) + local top = {} + + for player_index, items in pairs(crafted) do + local record = {player_index=player_index, count=0} + + for _, count in pairs(items) do + record.count = record.count + count + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.crafters) end -function Statistics.calculate_repairemans() -- NotImplemented +function Statistics.calculate_repairemans() + local repaired = Statistics.get_raw_data_type(Statistics.types.repaired) + local top = {} + + for player_index, items in pairs(repaired) do + local record = {player_index=player_index, count=0} + + for _, count in pairs(items) do + record.count = record.count + count + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.repairemans) end -function Statistics.calculate_wariors() -- NotImplemented +function Statistics.calculate_wariors() + local killed = Statistics.get_raw_data_type(Statistics.types.killed) + local top = {} + + for player_index, items in pairs(killed) do + if not items.enemy then + goto continue + end + + local record = {player_index=player_index, count=0} + + for _, damages in pairs(items.enemy) do + for name, count in pairs(damages) do + record.count = record.count + count + end + end + + table.insert(top, record) + + ::continue:: + end + + Statistics.sort_and_set_top(top, Statistics.tops.wariors) end -function Statistics.calculate_tree_haters() -- NotImplemented - -- body +function Statistics.calculate_tree_haters() + local killed = Statistics.get_raw_data_type(Statistics.types.killed) + local top = {} + + for player_index, items in pairs(killed) do + if not items.neutral then + goto next_player + end + + local record = {player_index=player_index, count=0} + + for item_name, damages in pairs(items.neutral) do + if not Statistics.is_tree(item_name) then + goto next_item + end + + for name, count in pairs(damages) do + record.count = record.count + count + end + + ::next_item:: + end + + table.insert(top, record) + + ::next_player:: + end + + Statistics.sort_and_set_top(top, Statistics.tops.tree_haters) end -function Statistics.calculate_rock_haters() -- NotImplemented - -- body +function Statistics.calculate_rock_haters() + local killed = Statistics.get_raw_data_type(Statistics.types.killed) + local top = {} + + for player_index, items in pairs(killed) do + if not items.neutral then + goto next_player + end + + local record = {player_index=player_index, count=0} + + for item_name, damages in pairs(items.neutral) do + if not Statistics.is_rock(item_name) then + goto next_item + end + + for name, count in pairs(damages) do + record.count = record.count + count + end + + ::next_item:: + end + + table.insert(top, record) + + ::next_player:: + end + + Statistics.sort_and_set_top(top, Statistics.tops.rock_haters) end -function Statistics.calculate_miners() -- NotImplemented - -- body +function Statistics.calculate_miners() + local mined = Statistics.get_raw_data_type(Statistics.types.mined) + local top = {} + + for player_index, items in pairs(mined) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if Statistics.is_minable(item_name) then + record.count = record.count + count + end + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.miners) end -function Statistics.calculate_sueciders() -- NotImplemented - -- body +function Statistics.calculate_deaths() + local deaths = Statistics.get_raw_data_type(Statistics.types.deaths) + local top = {} + + for player_index, forces in pairs(deaths) do + local record = {player_index=player_index, count=0} + + + for force_name, reasons in pairs(forces) do + if force_name ~= "unknown" then + for _, count in pairs(reasons) do + record.count = record.count + count + end + else + record.count = record.count + reasons + end + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.deaths) end -function Statistics.calculate_railwaymans() -- NotImplemented - -- body +function Statistics.calculate_railwaymans() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + local function calculate(items) + local total_count = 0 + + for item_name, count in pairs(items) do + if Statistics.is_railway_stuff(item_name) then + total_count = total_count + count + elseif item_name == "ghosts" then + total_count = total_count + calculate(count) + end + end + + return total_count + end + + for player_index, items in pairs(builded) do + table.insert(top, {player_index=player_index, count=calculate(items)}) + end + + Statistics.sort_and_set_top(top, Statistics.tops.railwaymans) end +function Statistics.calculate_runners() + local walked = Statistics.get_raw_data_type(Statistics.types.walked) + local top = {} + for player_index, transports in pairs(walked) do + local record = {player_index=player_index, count=0} --- Statistics utility functions -- + for _, count in pairs(transports) do + record.count = record.count + count + end + + table.insert(top, record) + end -function Statistics.get_player_default_rawdata() - return { - [Statistics.types.builded] = {}, - [Statistics.types.killed] = {}, - [Statistics.types.deaths] = {}, - [Statistics.types.repaired] = {}, - [Statistics.types.mined] = {}, - [Statistics.types.crafted] = {}, - [Statistics.types.walked] = {} - } + Statistics.sort_and_set_top(top, Statistics.tops.runners) end -function Statistics.get_player_rawdata_type(player_index, type_id) - if not global.statistics then -- Blow on water - Statistics.on_init() +function Statistics.calculate_lumberjacks() + local mined = Statistics.get_raw_data_type(Statistics.types.mined) + local top = {} + + for player_index, items in pairs(mined) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if item_name == "wood" then + record.count = record.count + count + end + end + + table.insert(top, record) end - if not global.statistics.rawdata[player_index] then - global.statistics.rawdata[player_index] = Statistics.get_player_default_rawdata() + Statistics.sort_and_set_top(top, Statistics.tops.lumberjacks) +end + +function Statistics.calculate_mariobrothers() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + for player_index, items in pairs(builded) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if Statistics.is_pipe(item_name) then + record.count = record.count + count + end + end + + table.insert(top, record) end - if not global.statistics.rawdata[player_index][type_id] then - global.statistics.rawdata[player_index][type_id] = {} + Statistics.sort_and_set_top(top, Statistics.tops.mariobrothers) +end + +function Statistics.calculate_oilmans() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + for player_index, items in pairs(builded) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if Statistics.is_oil_stuff(item_name) then + record.count = record.count + count + end + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.oilmans) +end + +function Statistics.calculate_roadworkers() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + for player_index, items in pairs(builded) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if Statistics.is_walkpath(item_name) then + record.count = record.count + count + end + end + + table.insert(top, record) end - return global.statistics.rawdata[player_index][type_id] + Statistics.sort_and_set_top(top, Statistics.tops.roadworkers) end -function Statistics.get_rawdata_type(type_id) - return global.statistics.rawdata[type_id] or {} +function Statistics.calculate_electricians() + local builded = Statistics.get_raw_data_type(Statistics.types.builded) + local top = {} + + for player_index, items in pairs(builded) do + local record = {player_index=player_index, count=0} + + for item_name, count in pairs(items) do + if Statistics.is_electric_pole(item_name) then + record.count = record.count + count + end + end + + table.insert(top, record) + end + + Statistics.sort_and_set_top(top, Statistics.tops.electricians) end -function Statistics.get_top(top_id) - return global.statistics.tops[top_id] or {} +function Statistics.calculate_fishermans() + local mined = Statistics.get_raw_data_type(Statistics.types.mined) + local top = {} + + for player_index, items in pairs(mined) do + if items["raw-fish"] then + local record = {player_index=player_index, count=items["raw-fish"]} + table.insert(top, record) + end + end + + Statistics.sort_and_set_top(top, Statistics.tops.fishermans) end +-- Statistics utility functions -- + +function Statistics.get_raw_data_type(type_name) + return global.statistics.raw_data[type_name] +end -function Statistics.sort_and_set_top(top, top_id) +function Statistics.get_player_raw_data_type(player_index, type_name) + local raw_data = Statistics.get_raw_data_type(type_name) + + if not raw_data[player_index] then + raw_data[player_index] = {} + end + + return raw_data[player_index] +end + +function Statistics.get_top(top_name) + return global.statistics.tops[top_name] or {} +end + + + +function Statistics.sort_and_set_top(top, top_name) table.sort(top, function(first, second) return first.count > second.count end) - global.statistics.tops[top_id] = top + global.statistics.tops[top_name] = top end @@ -129,7 +465,7 @@ function Statistics.is_tree(entity_name) end function Statistics.is_minable(entity_name) - return string.match(entity_name, "ore") or entity_name == "wood" or entity_name == "stone" + return string.match(entity_name, "ore") or entity_name == "stone" or entity_name == "coal" end function Statistics.is_rock(entity_name) @@ -151,19 +487,39 @@ function Statistics.is_railway_stuff(entity_name) or entity_name == "cargo-wagon" or entity_name == "fluid-wagon" end +function Statistics.is_pipe(entity_name) + return entity_name == "pipe" or entity_name == "pipe-to-ground" +end + +function Statistics.is_electric_pole(entity_name) + return string.match(entity_name, "pole") or entity_name == "substation" +end + +function Statistics.is_walkpath(entity_name) + return entity_name == "landfill" or entity_name == "stone-path" + or entity_name == "concrete" or entity_name == "refined-concrete" + or entity_name == "hazard-concrete-left" or entity_name == "hazard-concrete-right" + or entity_name == "refined-hazard-concrete-left" or entity_name == "refined-hazard-concrete-right" +end + -- Events handlers -- function Statistics.on_init() global.statistics = global.statistics or {} - global.statistics.gui = global.statistics.gui or {} - global.statistics.rawdata = global.statistics.rawdata or {} - global.statistics.tops = global.statistics.tops or {} - for _, top_name in pairs(Statistics.tops) do + global.statistics.raw_data = global.statistics.raw_data or {} + for _, type_name in pairs(Statistics.type_names) do + global.statistics.raw_data[type_name] = global.statistics.raw_data[type_name] or {} + end + + global.statistics.tops = global.statistics.tops or {} + for _, top_name in pairs(Statistics.top_names) do global.statistics.tops[top_name] = global.statistics.tops[top_name] or {} end + + global.statistics.gui = global.statistics.gui or {} end function Statistics.on_configuration_changed(data) @@ -171,7 +527,12 @@ function Statistics.on_configuration_changed(data) end function Statistics.on_nth_tick(event) - -- Statistics["calculate_"..Statistics.tops[Statistics.counter]]() + -- local profiler = game.create_profiler() + Statistics["calculate_"..Statistics.top_names[Statistics.counter]]() + -- profiler.stop() + -- printp({"", Statistics.top_names[Statistics.counter], " - ", profiler}) + -- local top_name = Statistics.top_names[Statistics.counter] + -- printp(top_name..":\n\n"..serpent.block(Statistics.get_top(top_name))) if Statistics.counter < table_size(Statistics.tops) then Statistics.counter = Statistics.counter + 1 @@ -180,12 +541,6 @@ function Statistics.on_nth_tick(event) end end - - -function Statistics.on_player_created(event) - global.statistics.rawdata[event.player_index] = Statistics.get_player_default_rawdata() -end - function Statistics.on_player_joined_game(event) if not global.statistics then Statistics.on_init() @@ -197,20 +552,41 @@ function Statistics.on_player_joined_game(event) end end + + function Statistics.on_player_died(event) - local deaths = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.deaths) + local deaths = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.deaths) if event.cause then - deaths[event.cause.name] = (deaths[event.cause.name] or 0) + 1 + if event.cause.name == "character" then + local killed = Statistics.get_player_raw_data_type(event.cause.player.index, Statistics.types.killed) + + if not killed.pvp then + killed.pvp = {} + end + + killed.pvp[event.player_index] = (killed.pvp[event.player_index] or 0) + 1 + + if not deaths.pvp then + deaths.pvp = {} + end + + deaths.pvp[event.cause.player.index] = (deaths.pvp[event.cause.player.index] or 0) + 1 + else + if not deaths[event.cause.force.name] then + deaths[event.cause.force.name] = {} + end + + local force_deaths = deaths[event.cause.force.name] + force_deaths[event.cause.name] = (force_deaths[event.cause.name] or 0) + 1 + end else - deaths.undefined = (deaths.undefined or 0) + 1 + deaths.unknown = (deaths.unknown or 0) + 1 end end - - function Statistics.on_built_entity(event) - local builded = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.builded) + local builded = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.builded) if event.created_entity.name == "entity-ghost" then builded.ghosts = builded.ghosts or {} @@ -222,14 +598,14 @@ function Statistics.on_built_entity(event) end function Statistics.on_player_built_tile(event) - local builded = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.builded) + local builded = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.builded) builded[event.tile.name] = (builded[event.tile.name] or 0) + #event.tiles end function Statistics.on_player_repaired_entity(event) -- Counting not precisely, but tssss! - local repaired = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.repaired) + local repaired = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.repaired) if event.entity.name == "stone-wall" then repaired[event.entity.name] = (repaired[event.entity.name] or 0) + 4 @@ -239,15 +615,15 @@ function Statistics.on_player_repaired_entity(event) end function Statistics.on_entity_died(event) - if not event.force or event.force.name ~= "player" then + if not event.cause or event.cause.name ~= "character" then return end - if not event.cause or event.cause.name ~= "character" then + if event.entity.name == "character" then return end - local killed = Statistics.get_player_rawdata_type(event.cause.player.index, Statistics.types.killed) + local killed = Statistics.get_player_raw_data_type(event.cause.player.index, Statistics.types.killed) if not killed[event.entity.force.name] then killed[event.entity.force.name] = {} @@ -257,24 +633,22 @@ function Statistics.on_entity_died(event) killed[event.entity.force.name][event.entity.name] = {} end - local entity = killed[event.entity.force.name][event.entity.name] - local count = entity[event.damage_type.name] or 0 - - entity[event.damage_type.name] = count + 1 + local enemy = killed[event.entity.force.name][event.entity.name] + enemy[event.damage_type.name] = (enemy[event.damage_type.name] or 0) + 1 end function Statistics.on_player_mined_item(event) - local mined = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.mined) + local mined = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.mined) mined[event.item_stack.name] = (mined[event.item_stack.name] or 0) + event.item_stack.count end function Statistics.on_player_crafted_item(event) - local crafted = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.crafted) + local crafted = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.crafted) crafted[event.item_stack.name] = (crafted[event.item_stack.name] or 0) + event.item_stack.count end function Statistics.on_player_changed_position(event) - local walked = Statistics.get_player_rawdata_type(event.player_index, Statistics.types.walked) + local walked = Statistics.get_player_raw_data_type(event.player_index, Statistics.types.walked) local player = game.players[event.player_index] local count, vehicle @@ -288,31 +662,62 @@ function Statistics.on_player_changed_position(event) walked[vehicle] = count end +function Statistics.on_top(event) + local self_player = game.players[event.player_index] + if not event.parameter or event.parameter == "list" then + self_player.print({"statistics.heading-1", {"statistics.all-categories"}}) --- Profiler and debug -- + for index, top_name in pairs(Statistics.top_names) do + self_player.print({ + "", index, ". ", + {"statistics.heading-1", {"statistics."..top_name}}, " - ", + {"statistics."..top_name.."-info"} + }) + end + else + local top_id = tonumber(event.parameter) -local profiler, profiler_gui + if not top_id or top_id % 1 > 0 or top_id < 0 or top_id > #Statistics.top_names then + self_player.print({"statistics.wrong-parameter"}) + return + end -function printp(caption) - if not global.profiler_gui then - return - end + local top_name = Statistics.top_names[top_id] - global.profiler_gui.caption = caption -end + Statistics["calculate_"..top_name]() -function on_reinit(event) - Statistics.on_init() + local top = Statistics.get_top(top_name) + + if not top or #top == 0 then + self_player.print({"statistics.no-data"}) + return + end - global.statistics[event.player_index] = Statistics.get_player_default_rawdata() + local max_index = table_size(top) - if global.profiler_gui then - global.profiler_gui.destroy() - global.profiler_gui = nil + if max_index > 10 then + max_index = 10 + end + + self_player.print({"statistics.heading-1", {"statistics."..top_name}}, {0.8, 0.8, 0}) + self_player.print({"statistics.heading-3", {"statistics."..top_name.."-info"}}, {0.8, 0.8, 0.8}) + + for index = 1, max_index do + local player = game.players[top[index].player_index] + self_player.print(index..". "..player.name.." - "..top[index].count) + end end +end - global.profiler = nil + + +-- Profiler and debug -- + +function on_reinit(event) + -- global.statistics = nil + Statistics.on_init() + -- global.statistics.raw_data.deaths = {} end function on_toggle_profiler(event) @@ -320,32 +725,40 @@ function on_toggle_profiler(event) return end - if global.profiler_gui then - global.profiler_gui.destroy() - global.profiler_gui = nil - global.profiler = nil + if global.statistics.profiler_gui then + global.statistics.profiler_gui.destroy() + global.statistics.profiler_gui = nil return end - global.profiler_gui = game.players[event.player_index].gui.left.add{type="text-box", caption="New Profiler"} - global.profiler_gui.style.width = 400 - global.profiler_gui.style.height = 600 + global.statistics.profiler_gui = game.players[event.player_index].gui.left.add{type="text-box", caption="New Profiler"} + global.statistics.profiler_gui.style.width = 400 + global.statistics.profiler_gui.style.height = 600 - printp(serpent.block(global.statistics.rawdata[event.player_index])) + printp(serpent.block(global.statistics.raw_data)) end -function on_printall(event) - printp(serpent.block(global.statistics.rawdata)) +function on_print(event) + printp(serpent.block(global.statistics.raw_data)) end -function on_printself(event) - printp(serpent.block(global.statistics.rawdata[event.player_index])) +function printp(caption, add) + if not global.statistics.profiler_gui then + return + end + + if add then + global.statistics.profiler_gui.caption = {"", global.statistics.profiler_gui.caption, "\n", caption} + else + global.statistics.profiler_gui.caption = caption + end end + + -- commands.add_command("reinit", "", on_reinit) -commands.add_command("profiler", "", on_toggle_profiler) -commands.add_command("printall", "", on_printall) -commands.add_command("printself", "", on_printself) +-- commands.add_command("profiler", "", on_toggle_profiler) +-- commands.add_command("print", "", on_print) @@ -355,9 +768,8 @@ local events = {} events.on_init = Statistics.on_init events.on_configuration_changed = Statistics.on_configuration_changed -- events.on_nth_tick = {} --- events.on_nth_tick[300] = Statistics.on_nth_tick +-- events.on_nth_tick[180] = Statistics.on_nth_tick events.events = { - [defines.events.on_player_created] = Statistics.on_player_created, [defines.events.on_player_joined_game] = Statistics.on_player_joined_game, [defines.events.on_player_changed_position] = Statistics.on_player_changed_position, [defines.events.on_player_died] = Statistics.on_player_died, @@ -372,6 +784,9 @@ events.events = { EventHandler.add_lib(events) +commands.add_command("top", "", Statistics.on_top) + + --