oolite 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +125 -0
- data/Rakefile +40 -0
- data/bin/ooconfig +168 -0
- data/bin/ootrader +40 -0
- data/bin/ooupdatemarket +45 -0
- data/lib/oolite.rb +191 -0
- data/lib/oolite/csv_doc.rb +68 -0
- data/lib/oolite/market.rb +143 -0
- data/lib/oolite/market_file.rb +55 -0
- data/lib/oolite/save_file.rb +71 -0
- data/lib/oolite/trade.rb +213 -0
- data/lib/oolite/version.rb +3 -0
- data/oolite.gemspec +25 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a7c6827b7924ebbeca80991a4ce8557f68796687
|
4
|
+
data.tar.gz: 1910d5718f908f7f3726c6307c4060fb808916d7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8cf6dc36233b7896e6ae727a9190049d260c528249798d39ff242a21c95fa34fb627ed056d8927f9f6d108e031dac6ff3c294cf93db8d759bd9afbd569624e6e
|
7
|
+
data.tar.gz: ded361ce7720a382df492177d6c1bb55a6d1709ea7d31ed332682ef95529dc99e7452602713aee9413ddba63bc3610b12cf078e686f4b87d0df47bcb02d8cd86
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Jeff McAffee
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# Oolite
|
2
|
+
|
3
|
+
Utility scripts for monitoring the Oolite game's system markets and
|
4
|
+
providing trading suggestions based on the market data.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
If you wish to clone the repository:
|
9
|
+
|
10
|
+
$ git clone https://github.com/jmcaffee/oolite.git
|
11
|
+
$ cd oolite
|
12
|
+
$ bundle
|
13
|
+
|
14
|
+
# Use rake to install the gem
|
15
|
+
rake install
|
16
|
+
|
17
|
+
# To start a pry console using the local version of the gem
|
18
|
+
rake console
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install oolite
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
These scripts are provided as standalone utilities. Simply install
|
27
|
+
the gem as detailed above to provide the following commands:
|
28
|
+
|
29
|
+
ooconfig - configure the scripts (ie. your save file location)
|
30
|
+
ootrader - suggest the best trades based on current location and destination
|
31
|
+
ooupdatemarket - update the market data (pulls from your save file)
|
32
|
+
|
33
|
+
### ooconfig
|
34
|
+
|
35
|
+
`ooconfig` displays and edits the configuration file.
|
36
|
+
|
37
|
+
The oolite scripts will look for the config file starting in your current directory
|
38
|
+
and ascending the directory tree until it reaches the root, then look in your _home_
|
39
|
+
directory. I would suggest running your initial configuration from your home dir
|
40
|
+
so the scripts can always find the config file no matter where you call them from.
|
41
|
+
|
42
|
+
To get started, determine where your save file is located at and change to your
|
43
|
+
home directory.
|
44
|
+
|
45
|
+
# Assuming your save file is at ~/oolite-saves/Jameson.oolite-save
|
46
|
+
cd ~
|
47
|
+
ooconfig save_file_path ~/oolite-saves/Jameson.oolite-save
|
48
|
+
|
49
|
+
You can see where the config file is located at by running
|
50
|
+
|
51
|
+
ooconfig path
|
52
|
+
|
53
|
+
To see the current configuration values, run
|
54
|
+
|
55
|
+
ooconfig show
|
56
|
+
|
57
|
+
To see available commands/options, run
|
58
|
+
|
59
|
+
ooconfig
|
60
|
+
|
61
|
+
### ooupdatemarket
|
62
|
+
|
63
|
+
`ooupdatemarket` saves its data in the same directory as your game save file.
|
64
|
+
It also generates a `CSV` dump of the most recent market data for all visited
|
65
|
+
systems.
|
66
|
+
|
67
|
+
Note that the data is only current for the system you are located at when you
|
68
|
+
save your game. The other system data is retained from the last time you visited
|
69
|
+
the system, saved your game, and ran `ooupdatemarket`.
|
70
|
+
|
71
|
+
### ootrader
|
72
|
+
|
73
|
+
`ootrader` will ask you for your destination system based on existing data
|
74
|
+
(ie. you've visited the destination at least once, saved your game, and ran
|
75
|
+
`ooupdatemarket`), then calculate and display all profitable trades, then
|
76
|
+
display its suggested trades to make the most profit.
|
77
|
+
|
78
|
+
It uses the current market data, your available credits and max cargo space
|
79
|
+
to make its suggestions.
|
80
|
+
|
81
|
+
## Workflow (Gameflow?)
|
82
|
+
|
83
|
+
* Dock your ship in game
|
84
|
+
* Sell your current cargo
|
85
|
+
* Refuel you ship
|
86
|
+
* Save your game
|
87
|
+
|
88
|
+
In a terminal, update your market data
|
89
|
+
|
90
|
+
ooupdatemarket
|
91
|
+
|
92
|
+
Now see what it suggests for trades
|
93
|
+
|
94
|
+
ootrader
|
95
|
+
|
96
|
+
**Note:** you'll need to visit more than one system, save your game,
|
97
|
+
and run `ooupdatemarket` before you'll be able to choose any destinations.
|
98
|
+
|
99
|
+
* In game, make your trades/purchases
|
100
|
+
* Travel to your destination
|
101
|
+
* Profit
|
102
|
+
|
103
|
+
## About This Project
|
104
|
+
|
105
|
+
These scripts were thrown together over the course of a couple of days.
|
106
|
+
As such, the code is not the prettiest, and I'm sure it's ripe for
|
107
|
+
refactoring.
|
108
|
+
|
109
|
+
I know that there are OXPs that can perform the same functionality (and
|
110
|
+
they're in-game too!) but I'm just scratching my itch to code here.
|
111
|
+
|
112
|
+
If you find errors, please create issues in the issue tracker. If you'd like
|
113
|
+
to add additional features, fork the project and submit a pull request.
|
114
|
+
|
115
|
+
## Roadmap
|
116
|
+
|
117
|
+
* Refactor the code
|
118
|
+
|
119
|
+
## Contributing
|
120
|
+
|
121
|
+
1. Fork it ( https://github.com/[my-github-username]/oolite/fork )
|
122
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
123
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
124
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
125
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
desc 'start a console'
|
4
|
+
task :console do
|
5
|
+
require 'pry'
|
6
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
7
|
+
require 'oolite'
|
8
|
+
ARGV.clear
|
9
|
+
|
10
|
+
def console_help
|
11
|
+
puts <<CONSOLE_HELP
|
12
|
+
CONSOLE HELP
|
13
|
+
-------------
|
14
|
+
|
15
|
+
Starts a pry console and requires the *local* version of Oolite.
|
16
|
+
|
17
|
+
Search and load the Oolite configuration (defaults will be set if
|
18
|
+
no configuration file is found)
|
19
|
+
|
20
|
+
Oolite.configure
|
21
|
+
|
22
|
+
OR
|
23
|
+
|
24
|
+
Oolite.configure do |config|
|
25
|
+
config.some_setting = some_value
|
26
|
+
end
|
27
|
+
|
28
|
+
After a configuration has been instantiated, you can retrieve the
|
29
|
+
current configuration with
|
30
|
+
|
31
|
+
Oolite.configuration
|
32
|
+
|
33
|
+
|
34
|
+
CONSOLE_HELP
|
35
|
+
end
|
36
|
+
|
37
|
+
console_help
|
38
|
+
Pry.start
|
39
|
+
end
|
40
|
+
|
data/bin/ooconfig
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# vim: set ft=ruby
|
4
|
+
##############################################################################
|
5
|
+
# File:: ooconfig
|
6
|
+
# Purpose:: Configure the oolite utility
|
7
|
+
#
|
8
|
+
# Author:: Jeff McAffee 05/20/2015
|
9
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
10
|
+
# Website:: http://ktechsystems.com
|
11
|
+
##############################################################################
|
12
|
+
|
13
|
+
require 'pathname'
|
14
|
+
begin
|
15
|
+
require 'oolite'
|
16
|
+
rescue LoadError
|
17
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
18
|
+
require 'oolite'
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
class Main
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def usage
|
27
|
+
puts "Usage: #{File.basename($0)} [ CMD | OPTION VALUE ]"
|
28
|
+
puts
|
29
|
+
puts " Available commands:"
|
30
|
+
puts " show: show current configuration settings"
|
31
|
+
puts " path: show location of config file (if found)"
|
32
|
+
puts " update CATEGORY VALUES: update a category item"
|
33
|
+
puts " categories:"
|
34
|
+
puts " systems: accepts (in order) NAME ECONOMY GOVERNMENT TECHLEVEL"
|
35
|
+
puts
|
36
|
+
puts " Available options:"
|
37
|
+
puts " save_file_path: path to Oolite save file (~ is allowed)"
|
38
|
+
puts
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_settings
|
42
|
+
puts "= Current Configuration Settings ="
|
43
|
+
puts
|
44
|
+
Oolite.configure do |config|
|
45
|
+
vars = config.instance_variables.map { |v| v.to_s.gsub('@','') }
|
46
|
+
vars.each do |var|
|
47
|
+
puts "#{var}: #{emit_value(config.send(var))}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def emit_value val
|
53
|
+
case val
|
54
|
+
when Array
|
55
|
+
emit_array(val)
|
56
|
+
when Hash
|
57
|
+
emit_hash(val)
|
58
|
+
else
|
59
|
+
return val
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def emit_array val
|
64
|
+
nl = "\n"
|
65
|
+
indent = " "
|
66
|
+
output = nl.dup
|
67
|
+
|
68
|
+
val.each do |elem|
|
69
|
+
output << indent << elem << nl
|
70
|
+
end
|
71
|
+
output << nl
|
72
|
+
end
|
73
|
+
|
74
|
+
def emit_hash val
|
75
|
+
nl = "\n"
|
76
|
+
indent = " "
|
77
|
+
output = nl.dup
|
78
|
+
|
79
|
+
val.each do |key,elem|
|
80
|
+
output << indent << "#{key}: " << indent << emit_value(elem) << nl
|
81
|
+
end
|
82
|
+
output
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_config_values args
|
86
|
+
Oolite.configure do |config|
|
87
|
+
while args.count > 0
|
88
|
+
var = args.shift
|
89
|
+
val = args.shift
|
90
|
+
config.send("#{var}=", val)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
Oolite.save_configuration
|
95
|
+
end
|
96
|
+
|
97
|
+
def system_data args
|
98
|
+
econ = args.shift
|
99
|
+
gov = args.shift
|
100
|
+
tech = args.shift
|
101
|
+
|
102
|
+
data = Hash.new
|
103
|
+
data[:economy] = econ unless econ.nil?
|
104
|
+
data[:government] = gov unless gov.nil?
|
105
|
+
data[:tech_level] = tech unless tech.nil?
|
106
|
+
|
107
|
+
data
|
108
|
+
end
|
109
|
+
|
110
|
+
def update args
|
111
|
+
category = args.shift
|
112
|
+
case category
|
113
|
+
when "systems"
|
114
|
+
Oolite.configure do |config|
|
115
|
+
name = args.shift
|
116
|
+
val = config.systems.fetch(name, Hash.new)
|
117
|
+
#val = val.merge( { name => system_data(args) } )
|
118
|
+
val = val.merge( system_data(args) )
|
119
|
+
config.systems[name] = val
|
120
|
+
end
|
121
|
+
|
122
|
+
Oolite.save_configuration
|
123
|
+
else
|
124
|
+
puts "Unknown category: #{category}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def process_cmd args
|
129
|
+
return false unless args.count > 0
|
130
|
+
|
131
|
+
if args.first.downcase == 'show'
|
132
|
+
current_settings
|
133
|
+
return true
|
134
|
+
end
|
135
|
+
|
136
|
+
if args.first.downcase == 'path'
|
137
|
+
path = Oolite.find_config_path
|
138
|
+
path = 'Not found' if path.nil? || path.to_s.empty?
|
139
|
+
puts "path: #{path}"
|
140
|
+
return true
|
141
|
+
end
|
142
|
+
|
143
|
+
if args.first.downcase == 'update'
|
144
|
+
args.shift
|
145
|
+
update args
|
146
|
+
return true
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
public
|
151
|
+
|
152
|
+
def execute args
|
153
|
+
if process_cmd(args)
|
154
|
+
return 0
|
155
|
+
end
|
156
|
+
|
157
|
+
if args.count < 2
|
158
|
+
|
159
|
+
usage
|
160
|
+
return 1
|
161
|
+
end
|
162
|
+
|
163
|
+
set_config_values args
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
Main.new.execute ARGV
|
168
|
+
|
data/bin/ootrader
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# vim: set ft=ruby
|
4
|
+
##############################################################################
|
5
|
+
# File:: ootrader
|
6
|
+
# Purpose:: Determine the best items to buy based on the current location
|
7
|
+
# and the next destination
|
8
|
+
#
|
9
|
+
# Author:: Jeff McAffee 05/20/2015
|
10
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
11
|
+
# Website:: http://ktechsystems.com
|
12
|
+
##############################################################################
|
13
|
+
|
14
|
+
require 'pathname'
|
15
|
+
begin
|
16
|
+
require 'oolite'
|
17
|
+
rescue LoadError
|
18
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
19
|
+
require 'oolite'
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
class Main
|
24
|
+
|
25
|
+
def execute
|
26
|
+
savefile = Oolite.configuration.save_file_path
|
27
|
+
if savefile.nil? || savefile.empty?
|
28
|
+
fail "save file path not set.\nUse 'ooconfig save_file_path YOUR_PATH' to set."
|
29
|
+
end
|
30
|
+
|
31
|
+
# Update the market file so we're working with the latest data.
|
32
|
+
market = Oolite::Market.new
|
33
|
+
market.update
|
34
|
+
|
35
|
+
# Display the best trades.
|
36
|
+
trader = Oolite::Trade.new.display
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Main.new.execute
|
data/bin/ooupdatemarket
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# vim: set ft=ruby
|
4
|
+
##############################################################################
|
5
|
+
# File:: ooupdatemarket
|
6
|
+
# Purpose:: Parse the Oolite save file and generate market info based on the
|
7
|
+
# current docked location's market
|
8
|
+
#
|
9
|
+
# Author:: Jeff McAffee 05/19/2015
|
10
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
11
|
+
# Website:: http://ktechsystems.com
|
12
|
+
##############################################################################
|
13
|
+
|
14
|
+
require 'pathname'
|
15
|
+
begin
|
16
|
+
require 'oolite'
|
17
|
+
rescue LoadError
|
18
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
19
|
+
require 'oolite'
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
class Main
|
24
|
+
|
25
|
+
def execute
|
26
|
+
savefile = Oolite.configuration.save_file_path
|
27
|
+
if savefile.nil? || savefile.empty?
|
28
|
+
fail "save file path not set.\nUse 'ooconfig save_file_path YOUR_PATH' to set."
|
29
|
+
end
|
30
|
+
|
31
|
+
market = Oolite::Market.new
|
32
|
+
market.update
|
33
|
+
market.write_csv
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if ARGV.count > 0 && ARGV.first.downcase == 'upgrade'
|
38
|
+
market = Oolite::Market.new
|
39
|
+
market.upgrade
|
40
|
+
elsif ARGV.count > 0 && ARGV.first.downcase == 'upgradeprice'
|
41
|
+
market = Oolite::Market.new
|
42
|
+
market.upgrade_price
|
43
|
+
else
|
44
|
+
Main.new.execute
|
45
|
+
end
|
data/lib/oolite.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
require "oolite/version"
|
2
|
+
|
3
|
+
if ENV['DEBUG'].nil?
|
4
|
+
$debug = false
|
5
|
+
else
|
6
|
+
$debug = true
|
7
|
+
end
|
8
|
+
|
9
|
+
module Oolite
|
10
|
+
CONFIG_FILE_NAME = '.oolite'
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :configuration
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Setup oolite configuration
|
18
|
+
#
|
19
|
+
# Attempts to find and load a configuration file the first time
|
20
|
+
# it's requested. If a config file cannot be found in the current
|
21
|
+
# directory tree (moving towards trunk, not the leaves), the user's
|
22
|
+
# home directory will be searched. If still not found, a default
|
23
|
+
# configuration object is created.
|
24
|
+
#
|
25
|
+
# If a block is provided, the configuration object is yielded to the block
|
26
|
+
# after the configuration is loaded/created.
|
27
|
+
#
|
28
|
+
|
29
|
+
def self.configure
|
30
|
+
if self.configuration.nil?
|
31
|
+
unless self.load_configuration
|
32
|
+
self.configuration = Configuration.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
yield(configuration) if block_given?
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Walk up the directory tree from current working dir (pwd) till a file
|
40
|
+
# named .oolite is found
|
41
|
+
#
|
42
|
+
# Returns file path if found, nil if not.
|
43
|
+
#
|
44
|
+
|
45
|
+
def self.find_config_path
|
46
|
+
path = Pathname(Pathname.pwd).ascend{|d| h=d+CONFIG_FILE_NAME; break h if h.file?}
|
47
|
+
if path.nil? && (Pathname(ENV['HOME']) + CONFIG_FILE_NAME).exist?
|
48
|
+
path = Pathname(ENV['HOME']) + CONFIG_FILE_NAME
|
49
|
+
end
|
50
|
+
path
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Write configuration to disk
|
55
|
+
#
|
56
|
+
# Writes to current working dir (pwd) if path is nil
|
57
|
+
#
|
58
|
+
# Returns path of emitted file
|
59
|
+
#
|
60
|
+
|
61
|
+
def self.save_configuration(path = nil)
|
62
|
+
# If no path provided, see if we can find one in the dir tree.
|
63
|
+
if path.nil?
|
64
|
+
path = find_config_path
|
65
|
+
end
|
66
|
+
|
67
|
+
# Still no path? Use the current working dir.
|
68
|
+
if path.nil?
|
69
|
+
path = Pathname.pwd
|
70
|
+
end
|
71
|
+
|
72
|
+
unless path.to_s.end_with?('/' + CONFIG_FILE_NAME)
|
73
|
+
path = Pathname(path) + CONFIG_FILE_NAME
|
74
|
+
end
|
75
|
+
|
76
|
+
path = Pathname(path).expand_path
|
77
|
+
File.write(path, YAML.dump(configuration))
|
78
|
+
|
79
|
+
path
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Load the configuration from disk
|
84
|
+
#
|
85
|
+
# Returns true if config file found and loaded, false otherwise.
|
86
|
+
#
|
87
|
+
|
88
|
+
def self.load_configuration(path = nil)
|
89
|
+
# If no path provided, see if we can find one in the dir tree.
|
90
|
+
if path.nil?
|
91
|
+
path = find_config_path
|
92
|
+
end
|
93
|
+
|
94
|
+
return false if path.nil?
|
95
|
+
return false unless Pathname(path).exist?
|
96
|
+
|
97
|
+
File.open(path, 'r') do |f|
|
98
|
+
self.configuration = YAML.load(f)
|
99
|
+
puts "configuration loaded from #{path}" if $debug
|
100
|
+
end
|
101
|
+
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
class Configuration
|
106
|
+
attr_accessor :save_file_path
|
107
|
+
attr_accessor :market_data_filename
|
108
|
+
attr_accessor :current_system_name
|
109
|
+
attr_accessor :current_credits
|
110
|
+
attr_accessor :cargo
|
111
|
+
attr_accessor :trade_contraband
|
112
|
+
attr_accessor :contraband
|
113
|
+
attr_accessor :economies
|
114
|
+
attr_accessor :governments
|
115
|
+
attr_accessor :systems
|
116
|
+
|
117
|
+
|
118
|
+
def initialize
|
119
|
+
reset
|
120
|
+
end
|
121
|
+
|
122
|
+
def reset
|
123
|
+
@save_file_path = ''
|
124
|
+
|
125
|
+
@market_data_filename = 'oolite.market'
|
126
|
+
|
127
|
+
@current_system_name = ''
|
128
|
+
@current_credits = 0
|
129
|
+
@cargo = 0
|
130
|
+
|
131
|
+
@trade_contraband = false
|
132
|
+
|
133
|
+
@contraband = [
|
134
|
+
"Slaves",
|
135
|
+
"Narcotics",
|
136
|
+
"Firearms",
|
137
|
+
]
|
138
|
+
|
139
|
+
@economies = [
|
140
|
+
"Rich Industrial",
|
141
|
+
"Average Industrial",
|
142
|
+
"Poor Industrial",
|
143
|
+
"Mainly Industrial",
|
144
|
+
"Mainly Agricultural",
|
145
|
+
"Rich Agricultural",
|
146
|
+
"Average Agricultural",
|
147
|
+
"Poor Agricultural"
|
148
|
+
]
|
149
|
+
|
150
|
+
@governments = [
|
151
|
+
"Anarchy",
|
152
|
+
"Feudal",
|
153
|
+
"Multi-Government",
|
154
|
+
"Dictatorship",
|
155
|
+
"Communist",
|
156
|
+
"Confederacy",
|
157
|
+
"Democracy",
|
158
|
+
"Corporate State"
|
159
|
+
]
|
160
|
+
|
161
|
+
@systems = Hash.new
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Control which instance vars are emitted when dumped to YAML.
|
166
|
+
# Example - not used at this time.
|
167
|
+
#
|
168
|
+
|
169
|
+
def encode_with(coder)
|
170
|
+
vars = instance_variables.map { |x| x.to_s }
|
171
|
+
vars = vars - ["@dummy"]
|
172
|
+
|
173
|
+
vars.each do |var|
|
174
|
+
var_val = eval(var)
|
175
|
+
coder[var.gsub('@', '')] = var_val
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end # Configuration
|
179
|
+
end
|
180
|
+
|
181
|
+
require 'yaml'
|
182
|
+
|
183
|
+
# Initialize the configuration
|
184
|
+
Oolite.configure
|
185
|
+
|
186
|
+
require 'oolite/csv_doc'
|
187
|
+
require 'oolite/save_file'
|
188
|
+
require 'oolite/market_file'
|
189
|
+
require 'oolite/market'
|
190
|
+
require 'oolite/trade'
|
191
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# File:: csv_doc.rb
|
3
|
+
# Purpose:: CSVDoc class for emitting formatted CSV documents
|
4
|
+
#
|
5
|
+
# Author:: Jeff McAffee 05/19/2015
|
6
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
7
|
+
# Website:: http://ktechsystems.com
|
8
|
+
##############################################################################
|
9
|
+
|
10
|
+
|
11
|
+
module Oolite
|
12
|
+
class CSVDoc
|
13
|
+
def lines
|
14
|
+
@lines ||= Array.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def add line = []
|
18
|
+
new_line = Array.new
|
19
|
+
|
20
|
+
Array(line).each do |elem|
|
21
|
+
if elem.include?(',')
|
22
|
+
# Quote element if it contains a comma
|
23
|
+
new_line << "\"#{elem}\""
|
24
|
+
else
|
25
|
+
new_line << elem
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
lines << new_line
|
30
|
+
end
|
31
|
+
|
32
|
+
def write filepath
|
33
|
+
pad_lines
|
34
|
+
output_lines = Array.new
|
35
|
+
lines.each do |line|
|
36
|
+
output_lines << line.join(',')
|
37
|
+
end
|
38
|
+
|
39
|
+
File.open(filepath, 'w') do |f|
|
40
|
+
f.write(output_lines.join("\n"))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def pad_lines
|
45
|
+
max = 0
|
46
|
+
lines.each do |line|
|
47
|
+
len = line.count
|
48
|
+
if len > max
|
49
|
+
max = len
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
padded_lines = Array.new
|
54
|
+
lines.each do |line|
|
55
|
+
if line.count < max
|
56
|
+
pads = max = line.count
|
57
|
+
pads.times.each do
|
58
|
+
line << ''
|
59
|
+
end
|
60
|
+
end
|
61
|
+
padded_lines << line
|
62
|
+
end
|
63
|
+
|
64
|
+
@lines = padded_lines
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,143 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# File:: market.rb
|
3
|
+
# Purpose:: Write out a market data file
|
4
|
+
#
|
5
|
+
# Author:: Jeff McAffee 05/19/2015
|
6
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
7
|
+
# Website:: http://ktechsystems.com
|
8
|
+
##############################################################################
|
9
|
+
|
10
|
+
require 'pathname'
|
11
|
+
require 'yaml'
|
12
|
+
|
13
|
+
module Oolite
|
14
|
+
class Market
|
15
|
+
def initialize
|
16
|
+
Oolite.configure do |config|
|
17
|
+
@save_file_path = Pathname(config.save_file_path)
|
18
|
+
path = @save_file_path.dirname
|
19
|
+
@market_data_path = path + (Pathname(config.market_data_filename).to_s + '.yml')
|
20
|
+
@market_data_csv = path + (Pathname(config.market_data_filename).to_s + '.csv')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update filename = nil
|
25
|
+
filename ||= @save_file_path
|
26
|
+
|
27
|
+
savefile = SaveFile.new filename
|
28
|
+
|
29
|
+
add_credits_to_config savefile.credits
|
30
|
+
add_cargo_to_config savefile.cargo
|
31
|
+
|
32
|
+
system_name = savefile.current_system_name
|
33
|
+
add_system_to_config system_name
|
34
|
+
puts "Updating data for #{system_name} system"
|
35
|
+
|
36
|
+
data[system_name] = savefile.local_market_data
|
37
|
+
|
38
|
+
write_data_file
|
39
|
+
end
|
40
|
+
|
41
|
+
def upgrade
|
42
|
+
mf = MarketFile.new
|
43
|
+
old_data = mf.data
|
44
|
+
|
45
|
+
old_data.each do |key, d|
|
46
|
+
updated_hash = Hash.new
|
47
|
+
d.each do |item, price|
|
48
|
+
if price.class == Hash
|
49
|
+
updated_hash[item] = price
|
50
|
+
else
|
51
|
+
updated_hash[item] = { price: price, amount: 0 }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
data[key] = updated_hash
|
56
|
+
end
|
57
|
+
|
58
|
+
write_data_file
|
59
|
+
end
|
60
|
+
|
61
|
+
def upgrade_price
|
62
|
+
mf = MarketFile.new
|
63
|
+
old_data = mf.data
|
64
|
+
|
65
|
+
old_data.each do |key, d|
|
66
|
+
updated_hash = Hash.new
|
67
|
+
d.each do |item, info|
|
68
|
+
updated_hash[item] = { price: (info[:price] * 10).to_i, amount: info[:amount] }
|
69
|
+
end
|
70
|
+
|
71
|
+
data[key] = updated_hash
|
72
|
+
end
|
73
|
+
|
74
|
+
write_data_file
|
75
|
+
end
|
76
|
+
|
77
|
+
def write_csv filename = nil
|
78
|
+
filename ||= @market_data_csv
|
79
|
+
csv_doc = CSVDoc.new
|
80
|
+
format_data csv_doc
|
81
|
+
csv_doc.write filename
|
82
|
+
|
83
|
+
puts "CSV file written to #{filename}"
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def data
|
89
|
+
@data ||= MarketFile.new.data
|
90
|
+
end
|
91
|
+
|
92
|
+
def write_data_file
|
93
|
+
mf = MarketFile.new
|
94
|
+
mf.data = data
|
95
|
+
mf.write
|
96
|
+
end
|
97
|
+
|
98
|
+
def format_data csv_doc
|
99
|
+
line = Array.new
|
100
|
+
line << ''
|
101
|
+
line = line + data.keys
|
102
|
+
csv_doc.add line
|
103
|
+
|
104
|
+
data[data.keys.first].keys.each do |type|
|
105
|
+
line = Array(type)
|
106
|
+
data.each do |location, local_data|
|
107
|
+
line << (local_data[type][:price] / 10.0).to_s
|
108
|
+
end
|
109
|
+
csv_doc.add line
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_system_to_config system
|
114
|
+
Oolite.configure do |config|
|
115
|
+
config.current_system_name = system
|
116
|
+
|
117
|
+
unless config.systems.key?(system)
|
118
|
+
details = { economy: nil,
|
119
|
+
government: nil,
|
120
|
+
tech_level: nil,
|
121
|
+
}
|
122
|
+
config.systems[system] = details
|
123
|
+
end
|
124
|
+
end
|
125
|
+
Oolite.save_configuration
|
126
|
+
end
|
127
|
+
|
128
|
+
def add_credits_to_config credits
|
129
|
+
Oolite.configure do |config|
|
130
|
+
config.current_credits = credits
|
131
|
+
end
|
132
|
+
Oolite.save_configuration
|
133
|
+
end
|
134
|
+
|
135
|
+
def add_cargo_to_config cargo
|
136
|
+
Oolite.configure do |config|
|
137
|
+
config.cargo = cargo
|
138
|
+
end
|
139
|
+
Oolite.save_configuration
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# File:: market_file.rb
|
3
|
+
# Purpose:: Store market data
|
4
|
+
#
|
5
|
+
# Author:: Jeff McAffee 05/20/2015
|
6
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
7
|
+
# Website:: http://ktechsystems.com
|
8
|
+
##############################################################################
|
9
|
+
|
10
|
+
require 'pathname'
|
11
|
+
require 'yaml'
|
12
|
+
|
13
|
+
module Oolite
|
14
|
+
class MarketFile
|
15
|
+
def initialize
|
16
|
+
Oolite.configure do |config|
|
17
|
+
@save_file_path = Pathname(config.save_file_path)
|
18
|
+
path = @save_file_path.dirname
|
19
|
+
@market_data_path = path + (Pathname(config.market_data_filename).to_s + '.yml')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def data
|
24
|
+
@data ||= self.load
|
25
|
+
end
|
26
|
+
|
27
|
+
def data= new_data
|
28
|
+
@data = new_data
|
29
|
+
end
|
30
|
+
|
31
|
+
def systems
|
32
|
+
data.keys
|
33
|
+
end
|
34
|
+
|
35
|
+
def load
|
36
|
+
if @market_data_path.nil? || @market_data_path.to_s.empty? || !@market_data_path.exist?
|
37
|
+
Hash.new
|
38
|
+
else
|
39
|
+
input = YAML.load_file(@market_data_path)
|
40
|
+
input or Hash.new
|
41
|
+
end
|
42
|
+
rescue
|
43
|
+
Hash.new
|
44
|
+
end
|
45
|
+
|
46
|
+
def write
|
47
|
+
raise "Missing filename" if @market_data_path.nil? || @market_data_path.to_s.empty?
|
48
|
+
|
49
|
+
File.open(@market_data_path, 'w') do |f|
|
50
|
+
f.write data.to_yaml
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# File:: save_file.rb
|
3
|
+
# Purpose:: Parse the Oolite save file
|
4
|
+
#
|
5
|
+
# Author:: Jeff McAffee 05/19/2015
|
6
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
7
|
+
# Website:: http://ktechsystems.com
|
8
|
+
##############################################################################
|
9
|
+
|
10
|
+
require 'pathname'
|
11
|
+
require 'nokogiri'
|
12
|
+
|
13
|
+
module Oolite
|
14
|
+
class SaveFile
|
15
|
+
def initialize filename
|
16
|
+
parse filename
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse filename
|
20
|
+
raise "Cannot find save file #{filename}" unless Pathname(filename).exist?
|
21
|
+
|
22
|
+
@doc = Nokogiri::XML(File.open(filename)) do |config|
|
23
|
+
config.noblanks
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def current_system_name
|
28
|
+
node = get_data_node_for_key 'current_system_name'
|
29
|
+
node.text
|
30
|
+
end
|
31
|
+
|
32
|
+
def cargo
|
33
|
+
node = get_data_node_for_key 'max_cargo'
|
34
|
+
node.text.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
def credits
|
38
|
+
node = get_data_node_for_key 'credits'
|
39
|
+
node.text.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
def local_market_data
|
43
|
+
node = get_data_node_for_key 'localMarket'
|
44
|
+
|
45
|
+
mdata = {}
|
46
|
+
|
47
|
+
node.children.each do |child|
|
48
|
+
type = child.children[0].text
|
49
|
+
amount = child.children[1].text.to_i
|
50
|
+
# Price is stored as an integer and displayed as price / 10.
|
51
|
+
price = child.children[2].text.to_i
|
52
|
+
mdata[type] = { amount: amount, price: price }
|
53
|
+
end
|
54
|
+
|
55
|
+
mdata
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def get_data_node_for_key key
|
61
|
+
@doc.css('dict').children.each do |node|
|
62
|
+
if node.name == 'key' && node.text == key
|
63
|
+
return node.next
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
raise "No data found for key #{key}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
data/lib/oolite/trade.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# File:: trade.rb
|
3
|
+
# Purpose:: Determine the best trades based on current location and the next
|
4
|
+
# destination
|
5
|
+
#
|
6
|
+
# Author:: Jeff McAffee 05/20/2015
|
7
|
+
# Copyright:: Copyright (c) 2015, kTech Systems LLC. All rights reserved.
|
8
|
+
# Website:: http://ktechsystems.com
|
9
|
+
##############################################################################
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
require 'yaml'
|
13
|
+
|
14
|
+
module Oolite
|
15
|
+
class Trade
|
16
|
+
def display
|
17
|
+
puts "= Oolite Trader ="
|
18
|
+
puts
|
19
|
+
puts " Current Location: #{current_system_name}"
|
20
|
+
puts
|
21
|
+
puts " Available destinations:"
|
22
|
+
puts
|
23
|
+
|
24
|
+
systems = market.systems
|
25
|
+
systems.delete current_system_name
|
26
|
+
systems.each_with_index do |sys,i|
|
27
|
+
puts " #{i} - #{sys}"
|
28
|
+
end
|
29
|
+
puts
|
30
|
+
choice = ask " Choose your destination (q to abort): "
|
31
|
+
|
32
|
+
return if choice.downcase == 'q'
|
33
|
+
puts
|
34
|
+
|
35
|
+
dest_system = systems[choice.to_i]
|
36
|
+
|
37
|
+
puts " -- Suggested Trades (best to worst) for #{dest_system} --"
|
38
|
+
puts
|
39
|
+
puts " #{'Item'.ljust(14)} #{'Amt Avail'.to_s.ljust(10)} #{'PricePerUnit'.to_s.rjust(8)} #{'ProfitPerUnit'.to_s.rjust(12)}"
|
40
|
+
puts
|
41
|
+
|
42
|
+
avail_trades = all_trades(dest_system)
|
43
|
+
avail_trades.each do |trade|
|
44
|
+
puts " " + trade.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
puts
|
48
|
+
|
49
|
+
puts " -- Suggested Transactions for #{dest_system} --"
|
50
|
+
puts
|
51
|
+
puts " #{'Item'.ljust(14)} #{'Purch Amt'.to_s.ljust(10)} #{'Profit'.to_s.rjust(8)}"
|
52
|
+
puts
|
53
|
+
|
54
|
+
trans, total_profit = calc_best_trades avail_trades
|
55
|
+
trans.each do |tran|
|
56
|
+
name = tran[:item].name
|
57
|
+
revenue = tran[:item].revenue
|
58
|
+
amount = tran[:amount]
|
59
|
+
profit = revenue * amount
|
60
|
+
|
61
|
+
puts " #{name.ljust(14)} #{amount.to_s.ljust(10)} #{(profit / 10.0).to_s.rjust(8)}"
|
62
|
+
end
|
63
|
+
|
64
|
+
puts
|
65
|
+
puts "Total Profit: #{(total_profit / 10.0).to_s}"
|
66
|
+
puts
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def ask msg
|
73
|
+
print "#{msg}"
|
74
|
+
val = STDIN.getc
|
75
|
+
end
|
76
|
+
|
77
|
+
def current_system_name
|
78
|
+
Oolite.configuration.current_system_name
|
79
|
+
end
|
80
|
+
|
81
|
+
def market
|
82
|
+
if @market.nil?
|
83
|
+
@market = MarketFile.new
|
84
|
+
@market.data
|
85
|
+
end
|
86
|
+
@market
|
87
|
+
end
|
88
|
+
|
89
|
+
def all_trades dest_system
|
90
|
+
calculate_all_trades dest_system
|
91
|
+
end
|
92
|
+
|
93
|
+
class TradeItem
|
94
|
+
attr_accessor :name
|
95
|
+
attr_accessor :amount
|
96
|
+
attr_accessor :cost
|
97
|
+
attr_accessor :revenue
|
98
|
+
|
99
|
+
def initialize name, amount, cost, revenue
|
100
|
+
@name = name
|
101
|
+
@amount = amount
|
102
|
+
@cost = cost
|
103
|
+
@revenue = revenue
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s
|
107
|
+
"#{name.ljust(14)} #{amount.to_s.ljust(10)} #{(cost / 10.0).to_s.rjust(8)} #{(revenue / 10.0).to_s.rjust(12)}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def calculate_all_trades dest_system
|
112
|
+
src = market.data[current_system_name]
|
113
|
+
dest = market.data[dest_system]
|
114
|
+
|
115
|
+
# Remove contraband if configured.
|
116
|
+
if Oolite.configuration.trade_contraband == false
|
117
|
+
Oolite.configuration.contraband.each do |contr|
|
118
|
+
src.delete contr
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
positive_trades = Array.new
|
123
|
+
|
124
|
+
src.keys.each do |item|
|
125
|
+
sprice = src[item][:price]
|
126
|
+
amount = src[item][:amount]
|
127
|
+
dprice = dest[item][:price]
|
128
|
+
|
129
|
+
revenue = dprice - sprice
|
130
|
+
if revenue > 0.0 && amount > 0
|
131
|
+
positive_trades << TradeItem.new(item, amount, sprice, revenue)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
positive_trades.sort { |a,b| b.revenue <=> a.revenue }
|
136
|
+
end
|
137
|
+
|
138
|
+
def calc_best_trades trades
|
139
|
+
avail_cargo = Oolite.configuration.cargo
|
140
|
+
credits = Oolite.configuration.current_credits
|
141
|
+
|
142
|
+
if avail_cargo <= 0
|
143
|
+
return [[], 0]
|
144
|
+
end
|
145
|
+
|
146
|
+
affordable_trades = []
|
147
|
+
trades.each do |trade|
|
148
|
+
if trade.cost <= credits
|
149
|
+
affordable_trades << trade
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
if affordable_trades.count <= 0
|
154
|
+
return [[], 0]
|
155
|
+
end
|
156
|
+
|
157
|
+
balance = credits
|
158
|
+
cargo = avail_cargo
|
159
|
+
suggested_trades_expensive_first = []
|
160
|
+
affordable_trades.each do |trade|
|
161
|
+
max_amt_by_price = balance / trade.cost
|
162
|
+
max_amt_by_cargo = [cargo, trade.amount].min
|
163
|
+
max_amt = [max_amt_by_price, max_amt_by_cargo].min
|
164
|
+
|
165
|
+
balance = balance - (max_amt * trade.cost)
|
166
|
+
cargo = cargo - max_amt
|
167
|
+
|
168
|
+
if max_amt > 0
|
169
|
+
transaction = { item: trade, amount: max_amt }
|
170
|
+
suggested_trades_expensive_first << transaction.dup
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
expensive_first_total_profit = 0
|
175
|
+
suggested_trades_expensive_first.each do |transaction|
|
176
|
+
profit = transaction[:item].revenue * transaction[:amount]
|
177
|
+
expensive_first_total_profit += profit
|
178
|
+
end
|
179
|
+
|
180
|
+
balance = credits
|
181
|
+
cargo = avail_cargo
|
182
|
+
suggested_trades_cheap_first = []
|
183
|
+
# Sort the trades in ascending order.
|
184
|
+
cheap_affordable_trades = affordable_trades.sort { |a,b| a.revenue <=> b.revenue }
|
185
|
+
cheap_affordable_trades.each do |trade|
|
186
|
+
max_amt_by_price = balance / trade.cost
|
187
|
+
max_amt_by_cargo = [cargo, trade.amount].min
|
188
|
+
max_amt = [max_amt_by_price, max_amt_by_cargo].min
|
189
|
+
|
190
|
+
balance = balance - (max_amt * trade.cost)
|
191
|
+
cargo = cargo - max_amt
|
192
|
+
|
193
|
+
if max_amt > 0
|
194
|
+
transaction = { item: trade, amount: max_amt }
|
195
|
+
suggested_trades_cheap_first << transaction.dup
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
cheap_first_total_profit = 0
|
200
|
+
suggested_trades_cheap_first.each do |transaction|
|
201
|
+
profit = transaction[:item].revenue * transaction[:amount]
|
202
|
+
cheap_first_total_profit += profit
|
203
|
+
end
|
204
|
+
|
205
|
+
if expensive_first_total_profit > cheap_first_total_profit
|
206
|
+
return [suggested_trades_expensive_first, expensive_first_total_profit]
|
207
|
+
else
|
208
|
+
return [suggested_trades_cheap_first, cheap_first_total_profit]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
data/oolite.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'oolite/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "oolite"
|
8
|
+
spec.version = Oolite::VERSION
|
9
|
+
spec.authors = ["Jeff McAffee"]
|
10
|
+
spec.email = ["jeff@ktechsystems.com"]
|
11
|
+
spec.summary = %q{Utility scripts for the Oolite game}
|
12
|
+
spec.description = %q{Utility scripts for tracking markets and assisting with trading in the Oolite game.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
|
24
|
+
spec.add_runtime_dependency "nokogiri", "~> 1.6"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oolite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeff McAffee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
description: Utility scripts for tracking markets and assisting with trading in the
|
56
|
+
Oolite game.
|
57
|
+
email:
|
58
|
+
- jeff@ktechsystems.com
|
59
|
+
executables:
|
60
|
+
- ooconfig
|
61
|
+
- ootrader
|
62
|
+
- ooupdatemarket
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- ".gitignore"
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/ooconfig
|
72
|
+
- bin/ootrader
|
73
|
+
- bin/ooupdatemarket
|
74
|
+
- lib/oolite.rb
|
75
|
+
- lib/oolite/csv_doc.rb
|
76
|
+
- lib/oolite/market.rb
|
77
|
+
- lib/oolite/market_file.rb
|
78
|
+
- lib/oolite/save_file.rb
|
79
|
+
- lib/oolite/trade.rb
|
80
|
+
- lib/oolite/version.rb
|
81
|
+
- oolite.gemspec
|
82
|
+
homepage: ''
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.3.0
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: Utility scripts for the Oolite game
|
106
|
+
test_files: []
|
107
|
+
has_rdoc:
|