rangedtable.lua 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. -- RangedTable - table with range or group entries
  2. -- Author: Lucas Siqueira
  3. -- License: Public Domain / CC0.
  4. local RangedTable = {}
  5. RangedTable.__index = RangedTable
  6. setmetatable(RangedTable, {
  7. __call = function(class, ...)
  8. local instance = setmetatable({}, class)
  9. if instance.initialize then
  10. instance:initialize(...)
  11. end
  12. return instance
  13. end
  14. })
  15. local function cmp_number(k, t)
  16. for i = 1, #t do
  17. local entry = t[i]
  18. local range, v = entry[1], entry[2]
  19. if k >= range[1] and k <= range[2] then
  20. return v
  21. end
  22. end
  23. end
  24. local function cmp_group(k, t)
  25. for i = 1, #t do
  26. local entry = t[i]
  27. local group, v = entry[1], entry[2]
  28. for i = 1, #group do
  29. if k == group[i] then
  30. return v
  31. end
  32. end
  33. end
  34. end
  35. function RangedTable:get(k)
  36. local cmp = type(k) == "number" and cmp_number or cmp_group
  37. return cmp(k, self.ranges)
  38. end
  39. function RangedTable:keys()
  40. local i = 0
  41. return function()
  42. i = i + 1
  43. return self.ranges[i] and self.ranges[i][1] or nil
  44. end
  45. end
  46. function RangedTable:items()
  47. local i = 0
  48. return function()
  49. i = i + 1
  50. return self.ranges[i] and self.ranges[i][1] or nil,
  51. self.ranges[i] and self.ranges[i][2] or nil
  52. end
  53. end
  54. function RangedTable:values()
  55. local i = 0
  56. return function()
  57. i = i + 1
  58. return self.ranges[i] and self.ranges[i][2] or nil
  59. end
  60. end
  61. function RangedTable:choice()
  62. return self:get(math.random(1, self.max))
  63. end
  64. function RangedTable:initialize(t)
  65. self.ranges = {}
  66. for i = 1, #t do
  67. self.ranges[#self.ranges + 1] = t[i]
  68. end
  69. self:normalize()
  70. return self
  71. end
  72. function RangedTable:size()
  73. return #self.ranges
  74. end
  75. function RangedTable:normalize()
  76. local normalized = {}
  77. local sum = 1
  78. local range
  79. for i = 1, #self.ranges do
  80. local entry = self.ranges[i]
  81. local chance = entry[1]
  82. local content = entry[2]
  83. if type(chance) == "number" then
  84. range = chance
  85. elseif #chance == 1 then
  86. range = chance[1]
  87. elseif type(chance[1]) == "string" then
  88. return
  89. else
  90. range = chance[2] - chance[1] + 1
  91. end
  92. normalized[#normalized + 1] = {{sum, sum + range - 1}, content}
  93. sum = sum + range
  94. end
  95. self.ranges = normalized
  96. self.max = sum - 1
  97. end
  98. return RangedTable