oolite 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|