mirror of
https://github.com/Refactorio/RedMew.git
synced 2025-03-17 21:08:08 +02:00
Map poll (#1351)
* Add tests for map poll winner. * Add option to overwrite map poll mod pack
This commit is contained in:
parent
eae8e6f078
commit
6a07a97fbf
@ -16,7 +16,8 @@ Public.game_types = game_types
|
||||
local memory = {
|
||||
mod_pack_text = '',
|
||||
restarting = nil,
|
||||
use_map_poll_result = nil
|
||||
use_map_poll_result = nil,
|
||||
overwrite_mod_pack = nil
|
||||
}
|
||||
local start_game_data = {
|
||||
type = game_types.scenario,
|
||||
@ -207,6 +208,14 @@ function Public.set_use_map_poll_result_option(state)
|
||||
memory.use_map_poll_result = state
|
||||
end
|
||||
|
||||
function Public.get_overwrite_modpack_option()
|
||||
return memory.overwrite_mod_pack
|
||||
end
|
||||
|
||||
function Public.set_overwrite_modpack_option(state)
|
||||
memory.overwrite_mod_pack = state
|
||||
end
|
||||
|
||||
local main_frame_name = Gui.uid_name()
|
||||
local close_button_name = Gui.uid_name()
|
||||
local scenario_radio_button_name = Gui.uid_name()
|
||||
@ -215,6 +224,7 @@ local name_textfield_name = Gui.uid_name()
|
||||
local set_mod_pack_checkbox_name = Gui.uid_name()
|
||||
local mod_pack_name_textfield_name = Gui.uid_name()
|
||||
local use_map_poll_result_checkbox_name = Gui.uid_name()
|
||||
local overwrite_mod_pack_checkbox_name = Gui.uid_name()
|
||||
|
||||
Public._main_frame_name = main_frame_name
|
||||
Public._close_button_name = close_button_name
|
||||
@ -224,6 +234,7 @@ Public._name_textfield_name = name_textfield_name
|
||||
Public._set_mod_pack_checkbox_name = set_mod_pack_checkbox_name
|
||||
Public._mod_pack_name_textfield_name = mod_pack_name_textfield_name
|
||||
Public._use_map_poll_result_checkbox_name = use_map_poll_result_checkbox_name
|
||||
Public._overwrite_mod_pack_checkbox_name = overwrite_mod_pack_checkbox_name
|
||||
|
||||
local function value_of_type_or_deafult(value, value_type, default)
|
||||
if type(value) == value_type then
|
||||
@ -345,6 +356,15 @@ local function draw_main_frame(player)
|
||||
}
|
||||
end
|
||||
|
||||
if memory.overwrite_mod_pack ~= nil then
|
||||
main_frame.add {
|
||||
type = 'checkbox',
|
||||
name = overwrite_mod_pack_checkbox_name,
|
||||
caption = 'Overwrite map poll mod pack',
|
||||
state = memory.overwrite_mod_pack
|
||||
}
|
||||
end
|
||||
|
||||
local bottom_flow = main_frame.add {
|
||||
type = 'flow',
|
||||
direction = 'horizontal'
|
||||
@ -404,6 +424,11 @@ Gui.on_checked_state_changed(use_map_poll_result_checkbox_name, function(event)
|
||||
memory.use_map_poll_result = use_map_poll_result_checkbox.state
|
||||
end)
|
||||
|
||||
Gui.on_checked_state_changed(overwrite_mod_pack_checkbox_name, function(event)
|
||||
local overwrite_mod_pack_checkbox = event.element
|
||||
memory.overwrite_mod_pack = overwrite_mod_pack_checkbox.state
|
||||
end)
|
||||
|
||||
Gui.on_text_changed(mod_pack_name_textfield_name, function(event)
|
||||
local text = event.element.text
|
||||
start_game_data.mod_pack = text
|
||||
|
@ -1,6 +1,7 @@
|
||||
local Poll = require 'features.gui.poll'
|
||||
local Global = require 'utils.global'
|
||||
local Event = require 'utils.event'
|
||||
local PollUtils = require 'utils.poll_utils'
|
||||
local Server = require 'features.server'
|
||||
local Ranks = require 'resources.ranks'
|
||||
|
||||
@ -16,63 +17,78 @@ end)
|
||||
local normal_mod_pack = 'danger_ore23'
|
||||
local bobs_mod_pack = 'danger_ore_bobs2'
|
||||
|
||||
local maps = {{
|
||||
name = 'danger-ore-deadlock-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'terraforming (default)'
|
||||
}, {
|
||||
name = 'danger-ore-one-direction-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'one direction (line)'
|
||||
}, {
|
||||
name = 'danger-ore-3way-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = '3-way (T shape)'
|
||||
}, {
|
||||
name = 'danger-ore-chessboard-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'chessboard (random squares)'
|
||||
}, {
|
||||
name = 'danger-ore-chessboard-uniform-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'chessboard uniform (fixed squares)'
|
||||
}, {
|
||||
name = 'danger-ore-circles-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'circles (ore rings)'
|
||||
}, {
|
||||
name = 'danger-ore-gradient-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'gradient (smooth ore ratios)'
|
||||
}, {
|
||||
name = 'danger-ore-split-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'split (4x sectors)'
|
||||
}, {
|
||||
name = 'danger-ore-hub-spiral-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'hub-spiral (with void)'
|
||||
}, {
|
||||
name = 'danger-ore-spiral-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'spiral (without void)'
|
||||
}, {
|
||||
name = 'danger-ore-landfill-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'landfill (all tiles)'
|
||||
}, {
|
||||
name = 'danger-ore-patches-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'patches (ore islands in coal)'
|
||||
}, {
|
||||
name = 'danger-ore-xmas-tree-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'xmas tree (triangle)'
|
||||
}, {
|
||||
name = 'danger-bobs-ores',
|
||||
mod_pack = bobs_mod_pack,
|
||||
display_name = 'bob\'s mod (default map)'
|
||||
}}
|
||||
local maps = {
|
||||
{
|
||||
name = 'danger-ore-deadlock-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'terraforming (default)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-one-direction-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'one direction (line)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-3way-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = '3-way (T shape)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-chessboard-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'chessboard (random squares)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-chessboard-uniform-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'chessboard uniform (fixed squares)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-circles-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'circles (ore rings)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-gradient-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'gradient (smooth ore ratios)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-split-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'split (4x sectors)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-hub-spiral-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'hub-spiral (with void)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-spiral-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'spiral (without void)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-landfill-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'landfill (all tiles)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-patches-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'patches (ore islands in coal)'
|
||||
},
|
||||
{
|
||||
name = 'danger-ore-xmas-tree-beltboxes-ore-only',
|
||||
mod_pack = normal_mod_pack,
|
||||
display_name = 'xmas tree (triangle)'
|
||||
},
|
||||
{
|
||||
name = 'danger-bobs-ores',
|
||||
mod_pack = bobs_mod_pack,
|
||||
display_name = 'bob\'s mod (default map)'
|
||||
}
|
||||
}
|
||||
|
||||
Event.add(Server.events.on_server_started, function()
|
||||
if data.created then
|
||||
@ -107,32 +123,11 @@ function Public.get_next_map()
|
||||
end
|
||||
|
||||
local answers = poll_data.answers
|
||||
local vote_counts = {}
|
||||
for i, answer_data in pairs(answers) do
|
||||
vote_counts[i] = answer_data.voted_count
|
||||
end
|
||||
|
||||
local max_count = 0
|
||||
for i = 1, #vote_counts do
|
||||
local count = vote_counts[i] or 0
|
||||
if count > max_count then
|
||||
max_count = count
|
||||
end
|
||||
end
|
||||
|
||||
if max_count == 0 then
|
||||
local chosen_index = PollUtils.get_poll_winner(answers)
|
||||
if chosen_index == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local max_indexes = {}
|
||||
for i = 1, #vote_counts do
|
||||
local count = vote_counts[i] or 0
|
||||
if count == max_count then
|
||||
max_indexes[#max_indexes + 1] = i
|
||||
end
|
||||
end
|
||||
|
||||
local chosen_index = max_indexes[math.random(#max_indexes)]
|
||||
return maps[chosen_index]
|
||||
end
|
||||
|
||||
|
@ -19,6 +19,7 @@ return function(config)
|
||||
|
||||
Restart.set_start_game_data({type = Restart.game_types.scenario, name = config.scenario_name or 'danger-ore-next'})
|
||||
Restart.set_use_map_poll_result_option(true)
|
||||
Restart.set_overwrite_modpack_option(false)
|
||||
|
||||
local function can_restart(player)
|
||||
if player.admin then
|
||||
@ -202,7 +203,14 @@ return function(config)
|
||||
return
|
||||
end
|
||||
|
||||
Restart.set_start_game_data({type = Restart.game_types.scenario, name = map_data.name, mod_pack = map_data.mod_pack})
|
||||
local mod_pack_to_use
|
||||
if Restart.get_overwrite_modpack_option() then
|
||||
mod_pack_to_use = Restart.get_start_game_data().mod_pack
|
||||
else
|
||||
mod_pack_to_use = map_data.mod_pack
|
||||
end
|
||||
|
||||
Restart.set_start_game_data({type = Restart.game_types.scenario, name = map_data.name, mod_pack = mod_pack_to_use})
|
||||
end
|
||||
|
||||
Restart.register(can_restart, restart_callback, restart_requested)
|
||||
|
37
utils/poll_utils.lua
Normal file
37
utils/poll_utils.lua
Normal file
@ -0,0 +1,37 @@
|
||||
local Public = {}
|
||||
|
||||
--- Returns the index for the answer with the most votes.
|
||||
-- If there is a tie one index from the ties is picked randomly usign rng
|
||||
-- Returns nil if passed in zero answers.
|
||||
-- rng defaults to math.random if not provided.
|
||||
function Public.get_poll_winner(answers, rng)
|
||||
local rand = rng or math.random
|
||||
local vote_counts = {}
|
||||
for i, answer_data in pairs(answers) do
|
||||
vote_counts[i] = answer_data.voted_count or 0
|
||||
end
|
||||
|
||||
local max_count = -math.huge
|
||||
for i = 1, #vote_counts do
|
||||
local count = vote_counts[i]
|
||||
if count > max_count then
|
||||
max_count = count
|
||||
end
|
||||
end
|
||||
|
||||
if max_count == -math.huge then
|
||||
return nil
|
||||
end
|
||||
|
||||
local max_indexes = {}
|
||||
for i = 1, #vote_counts do
|
||||
local count = vote_counts[i]
|
||||
if count == max_count then
|
||||
max_indexes[#max_indexes + 1] = i
|
||||
end
|
||||
end
|
||||
|
||||
return max_indexes[rand(#max_indexes)]
|
||||
end
|
||||
|
||||
return Public
|
96
utils/poll_utils_tests.lua
Normal file
96
utils/poll_utils_tests.lua
Normal file
@ -0,0 +1,96 @@
|
||||
local Declare = require 'utils.test.declare'
|
||||
local PollUtils = require 'utils.poll_utils'
|
||||
local Assert = require 'utils.test.assert'
|
||||
|
||||
Declare.module({
|
||||
'utils',
|
||||
'poll_utils',
|
||||
'get_poll_winner'
|
||||
}, function()
|
||||
Declare.test('picks most voted answer', function()
|
||||
-- Arrange
|
||||
local answers = {
|
||||
{
|
||||
voted_count = 0
|
||||
},
|
||||
{
|
||||
voted_count = 3
|
||||
},
|
||||
{
|
||||
voted_count = 1
|
||||
}
|
||||
}
|
||||
|
||||
-- Act
|
||||
local actual = PollUtils.get_poll_winner(answers)
|
||||
|
||||
-- Assert
|
||||
Assert.equal(2, actual)
|
||||
end)
|
||||
|
||||
Declare.test('picks from tied answers', function()
|
||||
-- Arrange
|
||||
local answers = {
|
||||
{
|
||||
voted_count = 0
|
||||
},
|
||||
{
|
||||
voted_count = 3
|
||||
},
|
||||
{
|
||||
voted_count = 1
|
||||
},
|
||||
{
|
||||
voted_count = 3
|
||||
}
|
||||
}
|
||||
|
||||
local rng = function(count)
|
||||
Assert.equal(2, count)
|
||||
return 2 -- pick last.
|
||||
end
|
||||
|
||||
-- Act
|
||||
local actual = PollUtils.get_poll_winner(answers, rng)
|
||||
|
||||
-- Assert
|
||||
Assert.equal(4, actual)
|
||||
end)
|
||||
|
||||
Declare.test('picks from tied answers all zero', function()
|
||||
-- Arrange
|
||||
local answers = {
|
||||
{
|
||||
voted_count = 0
|
||||
},
|
||||
{
|
||||
voted_count = 0
|
||||
},
|
||||
{
|
||||
voted_count = 0
|
||||
}
|
||||
}
|
||||
|
||||
local rng = function(count)
|
||||
Assert.equal(3, count)
|
||||
return 2 -- pick middle.
|
||||
end
|
||||
|
||||
-- Act
|
||||
local actual = PollUtils.get_poll_winner(answers, rng)
|
||||
|
||||
-- Assert
|
||||
Assert.equal(2, actual)
|
||||
end)
|
||||
|
||||
Declare.test('returns nil when no answers', function()
|
||||
-- Arrange
|
||||
local answers = {}
|
||||
|
||||
-- Act
|
||||
local actual = PollUtils.get_poll_winner(answers)
|
||||
|
||||
-- Assert
|
||||
Assert.equal(nil, actual)
|
||||
end)
|
||||
end)
|
Loading…
x
Reference in New Issue
Block a user