Skip to content

Instantly share code, notes, and snippets.

@reactormonk
Created February 11, 2014 18:44
Show Gist options
  • Save reactormonk/a3e943ce2a9235b4c1be to your computer and use it in GitHub Desktop.
Save reactormonk/a3e943ce2a9235b4c1be to your computer and use it in GitHub Desktop.
import db_sqlite
import tables
import strutils
import hashes
import math
import algorithm
import sets
import sequtils
type TTypeID* = string
proc open*(): TDbConn =
result = open(connection="data/rub100-sqlite3-v1.db", user="trading", password="", database="data-dump")
const reactionsQuery = sql"SELECT map.schematicID, map.typeID, map.quantity, map.isInput, time.cycleTime from planetschematicstypemap as map, planetschematics as time WHERE time.schematicID = map.schematicID "
type
TSchematicID = string
TItem = object of TObject
typeID: TTypeID
amount: float
TReaction = object of TObject
inputs: TSet[TItem]
output: TItem
factories: float
TReactionRow = object
schematicID: TSchematicID
typeID: TTypeID
quantity: string
isInput: string
cycleTime: string
proc hash(x: TItem): THash = hash(x.typeID) !& hash(x.amount)
proc `*`(item: TItem, x: float): TItem =
TItem(typeID: item.typeID, amount: item.amount * x)
proc merge(x: var TReaction, y: TReaction) =
if x.output.typeID == y.output.typeID:
x.factories += y.factories
let tbl = indexBy(x.inputs, proc(input: TItem): TTypeID = input.typeID)
for input in y.inputs:
let id = input.typeID
if hasKey(tbl, id):
x.inputs.excl(tbl[id])
x.inputs.incl(TItem(typeID: id, amount: tbl[id].amount + input.amount))
else:
x.inputs.incl(input)
elif map(x.inputs, proc(i: TItem): TTypeID = i.typeID).contains(y.output.typeID):
## Replace the correspoding input of x with y.
for input in x.inputs:
if input.typeID == y.output.typeID:
let factor = y.output.amount / input.amount
x.inputs.excl(input)
for inp in y.inputs: x.inputs.incl(inp*factor)
x.factories += (factor * y.factories)
return
else:
assert(false, "neither same output nor input to attach to")
proc merge(reactions: seq[TReaction]): TReaction =
var
tbl = initTable[TTypeID, TReaction]()
foundOutput = false
inputs = initSet[TTypeID]()
for reaction in reactions:
let id = reaction.output.typeID
if hasKey(tbl, id):
tbl.mget(id).merge(reaction)
else:
tbl[id] = reaction
for input in reaction.inputs:
inputs.incl(input.typeID)
for reaction in reactions:
if not inputs.contains(reaction.output.typeID):
assert(foundOutput, "found two outputs")
foundOutput = true
result = reaction
tbl.del(reaction.output.typeID)
assert(foundOutput, "didn't find an output")
var deletedSomething = true
while len(tbl) > 0:
if not deletedSomething:
assert(false, "not converging")
deletedSomething = false
for input in result.inputs:
let id = input.typeID
if hasKey(tbl, id):
merge(result, tbl[id])
deletedSomething = true
tbl.del(id)
# Unlikely to change anytime soon, so hardcoded. Increases the
# amounts in all reactions that are faster.
const maxCycleTime = "3600"
proc makeItem(row: TReactionRow): TItem =
var amount: float
if row.cycleTime != maxCycleTime:
amount = (parseInt(row.quantity) * (parseInt(maxCycleTime)) / parseInt(row.cycleTime))
else:
amount = float(parseInt(row.quantity))
result = TItem(typeID: row.typeID, amount: amount)
proc reactions(): TTable[TTypeID, TReaction] =
result = initTable[TTypeID, TReaction]()
let db = db.open()
var grouping = initTable[TSchematicID, seq[TReactionRow]]()
for row in db.fastRows(reactionsQuery):
let id = TSchematicID(row[0])
if not grouping.hasKey(id): grouping[id] = @[]
grouping.mget(id).add(TReactionRow(schematicID: id, typeID: TTypeID(row[1]), quantity: row[2], isInput: row[3], cycleTime: row[4]))
for rows in values(grouping):
var
inputs = initSet[TItem](16)
output: TItem
for row in rows:
if row.isInput == "0":
output = makeItem(row)
else:
inputs.incl(makeItem(row))
result.add(output.typeID, TReaction(inputs: inputs, output: output, factories:1.0))
proc produceItem(reactions: TTable[TTypeID, TReaction], item: TItem): seq[TReaction] =
# For each reaction, this creates all possible sets of edges leading to this item
result = @[]
if not(hasKey(reactions, item.typeID)): return
# HOWTO:
# create P3: [ <ways to produce P2>, <ways to produce P2>] including
# P2 itself
# ... and product that.
var orderedInputs: seq[TItem] = @[]
for item in reactions[item.typeID].inputs: orderedInputs.add(item)
var possibilities: seq[seq[TReaction]] = @[]
let
current = reactions[item.typeID]
factor = item.amount / current.output.amount
for index, inp in orderedInputs:
# Pseudo-reaction for only using the current factory
possibilities.add(@[])
# var inputSet = initSet[TItem]()
# inputSet.incl(TItem(typeID: inp.TypeID, amount: inp.amount*factor))
# possibilities[index].add(TReaction(inputs: inputSet, output: inp, factories: 0))
for index, inpId in orderedInputs:
for input in reactions[inpID.typeID].inputs:
if reactions.hasKey(input.typeID):
let factor = input.amount / current.output.amount
var current = reactions[input.typeID]
for recursiveInput in current.inputs:
for path in produceItem(reactions, recursiveInput*factor):
possibilities[index].add(path)
for path in product(possibilities):
var tmp = reactions[item.typeID]
merge(tmp, merge(path))
result.add(tmp)
import unittest
if isMainModule:
let tbl = reactions()
# suite "produce":
# test "P1 material":
# let inputs = toSet(@[TItem(typeID: TTypeID("2308"), amount: 3000)])
# check produceItem(tbl, TItem(typeID: TTypeID("2389"), amount: 20)) == @[TReaction(inputs: inputs, output: TItem(typeID: TTypeID("2389"), amount: 20), factories: 1)]
echo(tbl)
echo(repr(produceItem(tbl, TItem(typeID: TTypeID("2389"), amount: 20))))
65 Superconductors 3600
66 Coolant 3600
67 Rocket Fuel 3600
68 Synthetic Oil 3600
69 Oxides 3600
70 Silicate Glass 3600
71 Transmitter 3600
72 Water-Cooled CPU 3600
73 Mechanical Parts 3600
74 Construction Blocks 3600
75 Enriched Uranium 3600
76 Consumer Electronics 3600
77 Miniature Electronics 3600
78 Nanites 3600
79 Biocells 3600
80 Microfiber Shielding 3600
81 Viral Agent 3600
82 Fertilizer 3600
83 Genetically Enhanced Livestock 3600
84 Livestock 3600
85 Polytextiles 3600
86 Test Cultures 3600
87 Supertensile Plastics 3600
88 Polyaramids 3600
89 Ukomi Superconductor 3600
90 Condensates 3600
91 Camera Drones 3600
92 Synthetic Synapses 3600
94 High-Tech Transmitter 3600
95 Gel-Matrix Biopaste 3600
96 Supercomputers 3600
97 Robotics 3600
98 Smartfab Units 3600
99 Nuclear Reactors 3600
100 Guidance Systems 3600
102 Neocoms 3600
103 Planetary Vehicles 3600
104 Biotech Research Reports 3600
105 Vaccines 3600
106 Industrial Explosives 3600
107 Hermetic Membranes 3600
108 Transcranial Microcontroller 3600
109 Data Chips 3600
110 Hazmat Detection Systems 3600
111 Cryoprotectant Solution 3600
112 Organic Mortar Applicators 3600
113 Sterile Conduits 3600
114 Nano-Factory 3600
115 Self-Harmonizing Power Core 3600
116 Recursive Computing Module 3600
117 Broadcast Node 3600
118 Integrity Response Drones 3600
119 Wetware Mainframe 3600
121 Water 1800
122 Plasmoids 1800
123 Electrolytes 1800
124 Oxygen 1800
125 Oxidizing Compound 1800
126 Reactive Metals 1800
127 Precious Metals 1800
128 Toxic Metals 1800
129 Chiral Structures 1800
130 Silicon 1800
131 Bacteria 1800
132 Biomass 1800
133 Proteins 1800
134 Biofuels 1800
135 Industrial Fibers 1800
65 2389 40 1
65 3645 40 1
65 9838 5 0
66 2390 40 1
66 3645 40 1
66 9832 5 0
67 2389 40 1
67 2390 40 1
67 9830 5 0
68 2390 40 1
68 3683 40 1
68 3691 5 0
69 2317 5 0
69 2392 40 1
69 3683 40 1
70 2392 40 1
70 3697 5 0
70 9828 40 1
71 2389 40 1
71 2401 40 1
71 9840 5 0
72 2328 5 0
72 2398 40 1
72 3645 40 1
73 2398 40 1
73 2399 40 1
73 3689 5 0
74 2398 40 1
74 2400 40 1
74 3828 5 0
75 44 5 0
75 2399 40 1
75 2400 40 1
76 2400 40 1
76 2401 40 1
76 9836 5 0
77 2401 40 1
77 9828 40 1
77 9842 5 0
78 2393 40 1
78 2398 40 1
78 2463 5 0
79 2329 5 0
79 2396 40 1
79 2399 40 1
80 2327 5 0
80 2397 40 1
80 9828 40 1
81 2393 40 1
81 3775 5 0
81 3779 40 1
82 2393 40 1
82 2395 40 1
82 3693 5 0
83 2395 40 1
83 3779 40 1
83 15317 5 0
84 2395 40 1
84 2396 40 1
84 3725 5 0
85 2396 40 1
85 2397 40 1
85 3695 5 0
86 2319 5 0
86 2393 40 1
86 3645 40 1
87 2312 5 0
87 3683 40 1
87 3779 40 1
88 2321 5 0
88 2392 40 1
88 2397 40 1
89 3691 10 1
89 9838 10 1
89 17136 3 0
90 2317 10 1
90 2344 3 0
90 9832 10 1
91 2345 3 0
91 3697 10 1
91 9830 10 1
92 2312 10 1
92 2319 10 1
92 2346 3 0
94 2321 10 1
94 9840 10 1
94 17898 3 0
95 2317 10 1
95 2329 10 1
95 2348 3 0
95 9838 10 1
96 2328 10 1
96 2349 3 0
96 9832 10 1
96 9836 10 1
97 3689 10 1
97 9836 10 1
97 9848 3 0
98 2351 3 0
98 3828 10 1
98 9842 10 1
99 44 10 1
99 2327 10 1
99 2352 3 0
100 2328 10 1
100 9834 3 0
100 9840 10 1
102 2329 10 1
102 2354 3 0
102 3697 10 1
103 2312 10 1
103 3689 10 1
103 9842 10 1
103 9846 3 0
104 2358 3 0
104 2463 10 1
104 3725 10 1
104 3828 10 1
105 3725 10 1
105 3775 10 1
105 28974 3 0
106 2360 3 0
106 3693 10 1
106 3695 10 1
107 2321 10 1
107 2361 3 0
107 15317 10 1
108 2329 10 1
108 2463 10 1
108 12836 3 0
109 2312 10 1
109 2327 10 1
109 17392 3 0
110 2366 3 0
110 3695 10 1
110 3775 10 1
110 9840 10 1
111 2319 10 1
111 2367 3 0
111 3691 10 1
111 3693 10 1
112 2344 6 1
112 2393 40 1
112 2870 1 0
112 9848 6 1
113 2351 6 1
113 2875 1 0
113 3645 40 1
113 28974 6 1
114 2360 6 1
114 2398 40 1
114 2869 1 0
114 17136 6 1
115 2345 6 1
115 2352 6 1
115 2361 6 1
115 2872 1 0
116 2346 6 1
116 2871 1 0
116 9834 6 1
116 12836 6 1
117 2354 6 1
117 2867 1 0
117 17392 6 1
117 17898 6 1
118 2348 6 1
118 2366 6 1
118 2868 1 0
118 9846 6 1
119 2349 6 1
119 2358 6 1
119 2367 6 1
119 2876 1 0
121 2268 3000 1
121 3645 20 0
122 2308 3000 1
122 2389 20 0
123 2309 3000 1
123 2390 20 0
124 2310 3000 1
124 3683 20 0
125 2311 3000 1
125 2392 20 0
126 2267 3000 1
126 2398 20 0
127 2270 3000 1
127 2399 20 0
128 2272 3000 1
128 2400 20 0
129 2306 3000 1
129 2401 20 0
130 2307 3000 1
130 9828 20 0
131 2073 3000 1
131 2393 20 0
132 2286 3000 1
132 3779 20 0
133 2287 3000 1
133 2395 20 0
134 2288 3000 1
134 2396 20 0
135 2305 3000 1
135 2397 20 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment