stockr 0.1.0 → 0.2.0
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.
- data/Gemfile +2 -0
- data/Gemfile.lock +8 -0
- data/README.rdoc +73 -26
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/bin/stockr +3 -1
- data/lib/stockr.rb +41 -21
- data/lib/stockr/export.rb +35 -10
- data/lib/stockr/import.rb +43 -0
- data/lib/stockr/part.rb +57 -30
- data/lib/stockr/web.rb +2 -2
- data/spec/data/export.txt +12 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/stockr/export_spec.rb +30 -0
- data/spec/stockr/part_spec.rb +14 -1
- data/spec/stockr_spec.rb +39 -35
- data/stockr.gemspec +88 -0
- metadata +45 -29
- data/LICENSE.txt +0 -20
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
specs:
|
|
3
3
|
diff-lcs (1.1.2)
|
|
4
|
+
eletro (0.1.1)
|
|
5
|
+
stick (>= 1.3.3)
|
|
6
|
+
facets (2.9.0)
|
|
4
7
|
git (1.2.5)
|
|
5
8
|
jeweler (1.5.1)
|
|
6
9
|
bundler (~> 1.0.0)
|
|
7
10
|
git (>= 1.2.5)
|
|
8
11
|
rake
|
|
12
|
+
multipart-post (1.0.1)
|
|
9
13
|
rack (1.2.1)
|
|
10
14
|
rake (0.8.7)
|
|
11
15
|
rcov (0.9.9)
|
|
@@ -21,6 +25,8 @@ GEM
|
|
|
21
25
|
sinatra (1.1.0)
|
|
22
26
|
rack (~> 1.1)
|
|
23
27
|
tilt (~> 1.1)
|
|
28
|
+
stick (1.3.3)
|
|
29
|
+
facets (>= 2.1.0)
|
|
24
30
|
tilt (1.1)
|
|
25
31
|
|
|
26
32
|
PLATFORMS
|
|
@@ -28,7 +34,9 @@ PLATFORMS
|
|
|
28
34
|
|
|
29
35
|
DEPENDENCIES
|
|
30
36
|
bundler (~> 1.0.0)
|
|
37
|
+
eletro
|
|
31
38
|
jeweler (~> 1.5.1)
|
|
39
|
+
multipart-post
|
|
32
40
|
rcov
|
|
33
41
|
redis
|
|
34
42
|
rspec (~> 2.1.0)
|
data/README.rdoc
CHANGED
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
= stockr
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
Keep your stock up to date.
|
|
5
|
-
|
|
6
|
-
Exports to a bunch of formats too.
|
|
4
|
+
Keep your stock up to date with easy bash editing and web view.
|
|
5
|
+
Some fancy stuff, oh, and it exports to a bunch of formats too.
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
== Use
|
|
10
9
|
|
|
10
|
+
stockr quantity name package and/or price
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
stockr 5 LM358
|
|
14
|
+
> 5x LM358
|
|
11
15
|
|
|
12
|
-
stockr +5 LM358
|
|
13
16
|
stockr -2 LM358
|
|
14
|
-
stockr LM358
|
|
15
17
|
> 3x LM358
|
|
16
18
|
|
|
19
|
+
stockr LM
|
|
20
|
+
> 3x LM358
|
|
21
|
+
|
|
22
|
+
stockr 2 LM338 DIP
|
|
23
|
+
stockr 2 LM338 0.50
|
|
24
|
+
stockr 2 LM338 SMD 0.50
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
=== Web View
|
|
29
|
+
|
|
30
|
+
stockr web
|
|
31
|
+
|
|
32
|
+
If a navigator windows doesn`t appear, try: http://localhost:4567
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
=== Part Find
|
|
36
|
+
|
|
37
|
+
Resistors:
|
|
38
|
+
|
|
39
|
+
Supposing you got 1k and 220R resistors, when you ask for "500R" we should see:
|
|
40
|
+
|
|
41
|
+
2x 1k Parallel
|
|
42
|
+
2x 220R Serie
|
|
43
|
+
|
|
44
|
+
Alternatives ICs (TODO)
|
|
45
|
+
|
|
46
|
+
This will need human linkage? Isn't there a world database for this?
|
|
47
|
+
|
|
17
48
|
=== Shop List
|
|
18
49
|
|
|
19
50
|
If stock goes under 1, shows how many of that item we need, so just ask for shop:
|
|
@@ -23,24 +54,25 @@ If stock goes under 1, shows how many of that item we need, so just ask for shop
|
|
|
23
54
|
>2x ATMEGA8
|
|
24
55
|
|
|
25
56
|
|
|
26
|
-
===
|
|
27
|
-
|
|
28
|
-
stockr web
|
|
57
|
+
=== Export formats
|
|
29
58
|
|
|
30
|
-
|
|
59
|
+
Export to a bunch of formats (online someday?)
|
|
31
60
|
|
|
32
|
-
|
|
61
|
+
stockr [format]
|
|
33
62
|
|
|
63
|
+
Available: txt, csv, pdf, html, xml.
|
|
34
64
|
|
|
35
65
|
|
|
36
|
-
===
|
|
66
|
+
=== Import formats
|
|
37
67
|
|
|
38
|
-
|
|
68
|
+
You can use the txt format as a backup store. And run:
|
|
39
69
|
|
|
40
|
-
|
|
70
|
+
stockr [file]
|
|
41
71
|
|
|
72
|
+
To import it.
|
|
42
73
|
|
|
43
74
|
|
|
75
|
+
= PT
|
|
44
76
|
|
|
45
77
|
== Usar
|
|
46
78
|
|
|
@@ -50,34 +82,49 @@ sudo gem install stockr
|
|
|
50
82
|
|
|
51
83
|
Como funfa:
|
|
52
84
|
|
|
53
|
-
|
|
54
|
-
|
|
85
|
+
stockr +5 LM358
|
|
86
|
+
stockr +2 LM1117
|
|
55
87
|
|
|
56
88
|
Dae tu vai, usa um LM em um circ:
|
|
57
89
|
|
|
58
|
-
|
|
90
|
+
stockr -1 LM1117
|
|
59
91
|
|
|
60
92
|
Opa, q q eu tenho de lm?
|
|
61
93
|
|
|
62
|
-
|
|
94
|
+
stockr LM
|
|
95
|
+
|
|
96
|
+
> 5x LM358
|
|
97
|
+
> 1x LM1117
|
|
63
98
|
|
|
64
|
-
|
|
65
|
-
|
|
99
|
+
Aceita preços também:
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
stockr 10 LM7805 0.95
|
|
103
|
+
> 10x LM7805 0.95 (9.50)
|
|
66
104
|
|
|
67
105
|
|
|
68
106
|
=== Shop List
|
|
69
|
-
Outra opcao eh colocar coisas negativas, ou qdo chegar em valor negativo, vc chama:
|
|
70
107
|
|
|
71
|
-
stockr
|
|
108
|
+
Quando se adiciona peças negativas (stockr -5 LM7805, por exemplo),
|
|
109
|
+
ou qdo uma chega em valor negativo, executando:
|
|
110
|
+
|
|
111
|
+
stockr shop
|
|
112
|
+
|
|
113
|
+
É exibida uma listagem de coisas faltando...
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
=== Interface Web
|
|
117
|
+
|
|
118
|
+
stockr web
|
|
119
|
+
|
|
120
|
+
Se uma janela do navegador não abrir, visite http://localhost:4567
|
|
72
121
|
|
|
73
|
-
Vem a lista de coisas faltando...
|
|
74
122
|
|
|
75
|
-
|
|
123
|
+
=== Exportar Dados
|
|
76
124
|
|
|
77
|
-
|
|
125
|
+
stockr [FORMATO]
|
|
78
126
|
|
|
79
|
-
|
|
80
|
-
Sugestoes/duvidas to ae.
|
|
127
|
+
Exporta seu estoque. FORMATO podendo ser txt, csv, pdf, html.....
|
|
81
128
|
|
|
82
129
|
|
|
83
130
|
|
data/Rakefile
CHANGED
|
@@ -20,7 +20,8 @@ Jeweler::Tasks.new do |gem|
|
|
|
20
20
|
gem.email = "x@nofxx.com"
|
|
21
21
|
gem.authors = ["Marcos Piccinini"]
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
# DEPRECATED?
|
|
24
|
+
# gem.add_runtime_dependency 'redis'
|
|
24
25
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
|
25
26
|
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
|
26
27
|
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.0
|
data/bin/stockr
CHANGED
data/lib/stockr.rb
CHANGED
|
@@ -1,22 +1,55 @@
|
|
|
1
1
|
require "rubygems"
|
|
2
2
|
require "redis"
|
|
3
|
+
require "eletro"
|
|
3
4
|
|
|
4
5
|
require "stockr/store"
|
|
5
6
|
require "stockr/part"
|
|
7
|
+
require "stockr/import"
|
|
6
8
|
require "stockr/export"
|
|
7
9
|
|
|
8
10
|
module Stockr
|
|
9
11
|
|
|
10
12
|
FORMATS = %w{ txt csv html pdf xml }
|
|
13
|
+
DOTFILE = ENV['HOME'] + "/.stockr"
|
|
14
|
+
# TECHUB = "http://techub.heroku.com"
|
|
15
|
+
TECHUB = "http://localhost:3000"
|
|
11
16
|
|
|
12
|
-
def self.print_parts(res)
|
|
13
|
-
return "Not found... go shop!" unless res && !res.empty?
|
|
14
|
-
res.map(&:facts).join("\n")
|
|
15
17
|
|
|
18
|
+
def self.get_user
|
|
19
|
+
unless File.exists?(DOTFILE)
|
|
20
|
+
puts "What\`s your techub username?"
|
|
21
|
+
name = gets.chomp
|
|
22
|
+
puts "Password?"
|
|
23
|
+
pass = gets.chomp
|
|
24
|
+
File.open(DOTFILE, "w") { |f| f << "name: #{name}\npass: #{pass}"}
|
|
25
|
+
end
|
|
26
|
+
@conf = YAML.load(File.read(DOTFILE))
|
|
27
|
+
[@conf["name"], @conf["pass"]]
|
|
16
28
|
end
|
|
17
29
|
|
|
30
|
+
def self.run(txt)
|
|
31
|
+
if txt.size == 1
|
|
32
|
+
if txt.join =~ /#{FORMATS.join('|')}/
|
|
33
|
+
f = Export.send(txt[0].to_sym)
|
|
34
|
+
"File saved! #{f}"
|
|
35
|
+
else
|
|
36
|
+
puts "Searching...#{txt.join}"
|
|
37
|
+
res = Part.search(txt.join.upcase)
|
|
38
|
+
puts (res && !res.empty?) ? Export.format(res) : "Not found... go shop!"
|
|
39
|
+
res
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
if part = Part.create_or_increment(*txt)
|
|
43
|
+
puts "Ok, #{part.facts}"
|
|
44
|
+
else
|
|
45
|
+
puts "Problems creating part..."
|
|
46
|
+
end
|
|
47
|
+
part
|
|
48
|
+
end
|
|
49
|
+
end
|
|
18
50
|
|
|
19
51
|
def self.work(txt)
|
|
52
|
+
get_user
|
|
20
53
|
txt = txt.split(" ") unless txt.is_a? Array
|
|
21
54
|
parse = txt
|
|
22
55
|
case parse.join
|
|
@@ -24,24 +57,11 @@ module Stockr
|
|
|
24
57
|
when "web" then
|
|
25
58
|
puts "Starting websever on port."
|
|
26
59
|
require "stockr/web"
|
|
27
|
-
when "shop" then
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"File saved! #{f}"
|
|
33
|
-
else
|
|
34
|
-
puts "Searching...#{txt.join}"
|
|
35
|
-
print_parts Part.search(txt.join.upcase)
|
|
36
|
-
end
|
|
37
|
-
else
|
|
38
|
-
if part = Part.create_or_increment(*parse)
|
|
39
|
-
return "Done. #{part.facts}"
|
|
40
|
-
else
|
|
41
|
-
"Problems creating part..."
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
60
|
+
when "shop" then puts Export.format(Part.missing)
|
|
61
|
+
when /load.*/ then Import.from_file txt[1] #ARGF
|
|
62
|
+
when /pull.*/ then Import.from_web
|
|
63
|
+
when /push.*/ then Export.to_web
|
|
64
|
+
else run(txt)
|
|
45
65
|
end
|
|
46
66
|
|
|
47
67
|
end
|
data/lib/stockr/export.rb
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
# Export Redis DB to various formats
|
|
4
4
|
#
|
|
5
5
|
#
|
|
6
|
+
|
|
7
|
+
require 'net/http/post/multipart'
|
|
8
|
+
|
|
6
9
|
module Stockr
|
|
7
10
|
|
|
8
11
|
class Export
|
|
@@ -17,18 +20,20 @@ module Stockr
|
|
|
17
20
|
@ts ||= Time.now.strftime("%y-%m-%d-%H-%M-%S")
|
|
18
21
|
end
|
|
19
22
|
|
|
20
|
-
def format
|
|
23
|
+
def format(data = Part.all)
|
|
24
|
+
return "Nada." unless data && !data.empty?
|
|
21
25
|
<<TXT
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
#
|
|
27
|
+
# Stockr Export
|
|
28
|
+
#
|
|
29
|
+
# #{Time.now.strftime("%d/%b/%Y %H:%M:%S")}
|
|
30
|
+
#
|
|
31
|
+
---------------------------------------------------------------------
|
|
27
32
|
|
|
28
|
-
#{
|
|
33
|
+
#{data.map(&:line).join("\n")}
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
Total: #{
|
|
35
|
+
---------------------------------------------------------------------
|
|
36
|
+
Total: #{data.size} Part(s). #{Part.sum(data)}
|
|
32
37
|
|
|
33
38
|
TXT
|
|
34
39
|
end
|
|
@@ -59,12 +64,32 @@ TXT
|
|
|
59
64
|
def xml
|
|
60
65
|
end
|
|
61
66
|
|
|
62
|
-
def write(txt, ext)
|
|
67
|
+
def write(txt, ext, path = nil)
|
|
63
68
|
fname = filename + ".#{ext}"
|
|
69
|
+
fname = path + fname if path
|
|
64
70
|
File.open(fname, "w") { |f| f << txt }
|
|
65
71
|
fname
|
|
66
72
|
end
|
|
67
73
|
|
|
74
|
+
def to_web
|
|
75
|
+
user, pass = Stockr.get_user unless user
|
|
76
|
+
file = write(format, :txt, "/tmp/")
|
|
77
|
+
puts "Exporting db to techub..."
|
|
78
|
+
url = URI.parse(TECHUB + "/push")
|
|
79
|
+
File.open(file) do |f|
|
|
80
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
|
81
|
+
req = Net::HTTP::Post::Multipart.new url.path, "file" => UploadIO.new(f, "text/plain", file)
|
|
82
|
+
req.basic_auth user, pass if pass
|
|
83
|
+
puts "Sending file..."
|
|
84
|
+
http.request(req)
|
|
85
|
+
puts req.body
|
|
86
|
+
end
|
|
87
|
+
puts "Done."
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
68
93
|
end
|
|
69
94
|
|
|
70
95
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
# require "net/http"
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Stockr
|
|
6
|
+
|
|
7
|
+
class Import
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
def import(l)
|
|
12
|
+
puts "Importing #{l}" #if Debug
|
|
13
|
+
_, qty, name, price = l.match(/^\s*([0-9]*)x\s*([^\.\s]*)\s*\.*\s*(\d*\.?\d*)/).to_a
|
|
14
|
+
return unless qty || name
|
|
15
|
+
Part.find_or_create(qty, name, price)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def from_file(file)
|
|
19
|
+
File.open(file).each_line { |l| import(l) }
|
|
20
|
+
"Loaded"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def from_web(user = nil)
|
|
24
|
+
user, pass = Stockr.get_user unless user
|
|
25
|
+
puts "Downloading dump file...#{TECHUB}/#{user}.txt"
|
|
26
|
+
puts url = URI.parse("#{TECHUB}/#{user}.txt")
|
|
27
|
+
Net::HTTP.start(url.host, url.port) { |http|
|
|
28
|
+
req = Net::HTTP::Get.new("/#{user}.txt")
|
|
29
|
+
req.basic_auth user, pass if pass
|
|
30
|
+
res = http.request(req)
|
|
31
|
+
puts "File downloaded, parsing..."
|
|
32
|
+
res.body.each_line { |l| import(l) }
|
|
33
|
+
}
|
|
34
|
+
puts "Done"
|
|
35
|
+
# puts res.body
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
data/lib/stockr/part.rb
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
module Stockr
|
|
4
4
|
|
|
5
5
|
class Part
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
attr_reader :name, :qty, :price, :pkg, :kind
|
|
8
|
+
|
|
9
|
+
CASH = "$ %.3f"
|
|
7
10
|
|
|
8
11
|
def initialize(name, qty = 0, pr = 0)
|
|
9
12
|
@name = name.upcase
|
|
@@ -13,23 +16,31 @@ module Stockr
|
|
|
13
16
|
|
|
14
17
|
def save
|
|
15
18
|
return false unless name && !name.empty?
|
|
16
|
-
Store.write(name, { :qty => qty, :price => price })
|
|
19
|
+
Store.write(name, { :qty => qty, :price => price, :pkg => pkg })
|
|
17
20
|
end
|
|
18
21
|
|
|
19
|
-
def
|
|
20
|
-
out = "#{qty}x
|
|
22
|
+
def line
|
|
23
|
+
out = "#{qty}#{' ' * (5-qty.to_s.size)}x #{name} #{pkg} "
|
|
21
24
|
if price && !price.zero?
|
|
22
25
|
out << ("." * (50 - out.size))
|
|
23
|
-
out <<
|
|
24
|
-
out << " ($ %.3f)" % (price * qty) if qty != 1
|
|
26
|
+
out << CASH % price
|
|
27
|
+
out << " ($ %.3f)" % (price * qty) #if qty != 1
|
|
25
28
|
end
|
|
26
29
|
out
|
|
27
30
|
end
|
|
28
31
|
|
|
32
|
+
def facts
|
|
33
|
+
out = "#{qty}x #{name} #{pkg} #{CASH} (#{CASH})" % [price, price_total]
|
|
34
|
+
end
|
|
35
|
+
|
|
29
36
|
def qty=(v)
|
|
30
37
|
@qty = v
|
|
31
38
|
end
|
|
32
39
|
|
|
40
|
+
def pkg=(p)
|
|
41
|
+
@pkg = p
|
|
42
|
+
end
|
|
43
|
+
|
|
33
44
|
def price=(pr)
|
|
34
45
|
# BigDecimal.new()
|
|
35
46
|
@price = pr.kind_of?(Numeric) ? pr.to_f : pr.gsub(",", ".").to_f
|
|
@@ -43,37 +54,53 @@ module Stockr
|
|
|
43
54
|
"{name: '#{name}', qty: '#{qty}', price: '%.3f', total_price: '%.3f'}" % [price, price_total]
|
|
44
55
|
end
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
part = search(name, true) || new(name)
|
|
48
|
-
incr ? part.qty += q.to_i : part.qty = q.to_i
|
|
49
|
-
part.price = pr
|
|
50
|
-
part.save
|
|
51
|
-
part
|
|
52
|
-
end
|
|
57
|
+
class << self
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
def sum(ary = search("*"))
|
|
60
|
+
CASH % ary.reduce(0) { |i, p| i += p.price_total }
|
|
61
|
+
end
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
def find_or_create(q, name, pr=0, incr = false)
|
|
64
|
+
part = search(name, true) || new(name)
|
|
65
|
+
incr ? part.qty += q.to_i : part.qty = q.to_i
|
|
66
|
+
if pr =~ /\d/
|
|
67
|
+
part.price = pr
|
|
68
|
+
else
|
|
69
|
+
part.pkg = pr
|
|
62
70
|
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
nil
|
|
71
|
+
part.save
|
|
72
|
+
part
|
|
66
73
|
end
|
|
67
|
-
end
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
def create_or_increment(q, name, pr=0)
|
|
76
|
+
find_or_create(q, name, pr, true)
|
|
77
|
+
end
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
def search(txt, exact = false)
|
|
80
|
+
if res = Store.find(exact ? txt : "*#{txt}*")
|
|
81
|
+
objs = res.map do |k, r|
|
|
82
|
+
new(k, r["qty"], r["price"])
|
|
83
|
+
end
|
|
84
|
+
exact ? objs[0] : objs # FIXME: better way?
|
|
85
|
+
else
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def all; search(''); end
|
|
91
|
+
|
|
92
|
+
def list(txt = "*")
|
|
93
|
+
search(txt).map(&:line) rescue []
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def find(txt)
|
|
97
|
+
search(txt, true)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def missing
|
|
101
|
+
all.select { |p| p.qty <= 0 }
|
|
102
|
+
end
|
|
74
103
|
|
|
75
|
-
def self.missing
|
|
76
|
-
all.select { |p| p.qty <= 0 }
|
|
77
104
|
end
|
|
78
105
|
|
|
79
106
|
|
data/lib/stockr/web.rb
CHANGED
|
@@ -11,7 +11,7 @@ get '/' do
|
|
|
11
11
|
parts = Part.all
|
|
12
12
|
@parts = parts.map(&:to_json)
|
|
13
13
|
@sum = parts.reduce(0) { |n, p| n += p.price_total }
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
erb <<INDEX
|
|
16
16
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
|
17
17
|
<html class="cufon-active cufon-ready"><head>
|
|
@@ -239,5 +239,5 @@ post '/' do
|
|
|
239
239
|
end
|
|
240
240
|
end
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
Sinatra::Application.run!
|
|
243
243
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Stockr Export
|
|
2
|
+
|
|
3
|
+
10-12-09-19-23-51
|
|
4
|
+
|
|
5
|
+
-------------------------------------------
|
|
6
|
+
|
|
7
|
+
100x 10K............................. 0.05 (5.00)
|
|
8
|
+
50x LM7805........................... 0.10 (5.00)
|
|
9
|
+
25x LM758............................ 1.00 (25.00)
|
|
10
|
+
|
|
11
|
+
-------------------------------------------
|
|
12
|
+
Total: 0
|
data/spec/spec_helper.rb
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Export" do
|
|
4
|
+
include Stockr
|
|
5
|
+
|
|
6
|
+
it "should export txt file" do
|
|
7
|
+
Time.should_receive(:now).exactly(2).times.and_return(Time.at(1291879432))
|
|
8
|
+
run("4 LM448")
|
|
9
|
+
run("txt").should eql("File saved! my_stockr_10-12-09-05-23-52.txt")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should export to html file" do
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
it "should import txt bkp" do
|
|
18
|
+
run("load ./spec/data/export.txt").should eql("Loaded")
|
|
19
|
+
Part.find("LM7805").qty.should eql(50)
|
|
20
|
+
Part.find("LM758").qty.should eql(25)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should import all values" do
|
|
24
|
+
run("load ./spec/data/export.txt").should eql("Loaded")
|
|
25
|
+
Part.all.size.should eql(3)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
data/spec/stockr/part_spec.rb
CHANGED
|
@@ -15,5 +15,18 @@ describe "Part" do
|
|
|
15
15
|
Part.new("IRF640", 10, "0,30").price.should be_within(0.1).of(0.3)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
it "should list all parts" do
|
|
19
|
+
run("-2 LM447")
|
|
20
|
+
run("2 LM448")
|
|
21
|
+
Part.all.should have(2).parts
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should list missing parts" do
|
|
25
|
+
run("-2 LM447")
|
|
26
|
+
run("2 LM448")
|
|
27
|
+
Part.missing.should have(1).part
|
|
28
|
+
Part.missing[0].name.should eql("LM447")
|
|
29
|
+
# run("shop").should eql("-2x LM447 $ 0.000 ($ -0.000)")
|
|
30
|
+
end
|
|
31
|
+
|
|
19
32
|
end
|
data/spec/stockr_spec.rb
CHANGED
|
@@ -1,78 +1,82 @@
|
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
|
3
3
|
describe "Stockr" do
|
|
4
|
+
include Stockr
|
|
4
5
|
|
|
5
|
-
def
|
|
6
|
-
|
|
6
|
+
def find(t)
|
|
7
|
+
Part.find(t)
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
it "should add parts" do
|
|
10
|
-
run("2 LM358").should
|
|
11
|
-
run("LM358").should
|
|
11
|
+
run("2 LM358").should be_a Part
|
|
12
|
+
run("LM358").should have(1).part
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
it "should add
|
|
15
|
-
run("100 1K").should eql("
|
|
16
|
-
|
|
15
|
+
it "should add part names" do
|
|
16
|
+
run("100 1K").name.should eql("1K")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should add part qty" do
|
|
20
|
+
run("100 1K").qty.should eql(100)
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
it "should increment existing parts" do
|
|
20
|
-
run("2 ATMEGA32").should eql("
|
|
21
|
-
run("2 ATMEGA32").should eql(
|
|
22
|
-
|
|
24
|
+
run("2 ATMEGA32").name.should eql("ATMEGA32")
|
|
25
|
+
run("2 ATMEGA32").qty.should eql(4)
|
|
26
|
+
Part.all.size.should eql(1)
|
|
27
|
+
find("ATMEGA32").qty.should eql(4)
|
|
23
28
|
end
|
|
24
29
|
|
|
25
30
|
it "should decrement existing parts" do
|
|
26
|
-
run("4 LM447")
|
|
27
|
-
run("-2 LM447")
|
|
31
|
+
run("4 LM447")
|
|
32
|
+
run("-2 LM447")
|
|
33
|
+
Part.all.size.should eql(1)
|
|
34
|
+
find("LM447").qty.should eql(2)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should parse nicely missing parts" do
|
|
38
|
+
run("-2 4N35").qty.should eql(-2)
|
|
28
39
|
end
|
|
29
40
|
|
|
30
41
|
it "should add missing parts" do
|
|
31
|
-
run("-2 LM447")
|
|
32
|
-
|
|
42
|
+
run("-2 LM447")
|
|
43
|
+
find("LM447").qty.should eql(-2)
|
|
44
|
+
run("2 LM447")
|
|
45
|
+
find("LM447").qty.should be_zero
|
|
33
46
|
end
|
|
34
47
|
|
|
35
|
-
it "should
|
|
36
|
-
run("
|
|
37
|
-
run("2
|
|
38
|
-
run("shop").should eql("-2x LM447")
|
|
48
|
+
it "should add pkgs to parts" do
|
|
49
|
+
run("2 LM338 DIP").pkg.should eql("DIP")
|
|
50
|
+
run("2 LM338 DIP").price.should be_zero
|
|
39
51
|
end
|
|
40
52
|
|
|
41
53
|
it "should add prices to parts" do
|
|
42
|
-
run("1 LM447
|
|
54
|
+
run("1 LM447 1.50").price.should be_within(0.1).of(1.5)
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
it "should add prices to multiple parts (sum)" do
|
|
46
|
-
run("2 LM447 0.50").should
|
|
58
|
+
run("2 LM447 0.50").price.should be_within(0.1).of(0.5)
|
|
47
59
|
end
|
|
48
60
|
|
|
49
61
|
it "should upcase the part name" do
|
|
50
|
-
run("8 enc28j60").should eql("
|
|
62
|
+
run("8 enc28j60").name.should eql("ENC28J60")
|
|
51
63
|
end
|
|
52
64
|
|
|
53
65
|
it "should be case insensitive" do
|
|
54
|
-
run("2 LM447")
|
|
55
|
-
run("lm447").should eql("
|
|
66
|
+
run("2 LM447")
|
|
67
|
+
run("lm447")[0].name.should eql(find("LM447").name)
|
|
56
68
|
end
|
|
57
69
|
|
|
58
70
|
it "should search pattern" do
|
|
59
|
-
run("4 LM447")
|
|
60
|
-
run("4 LM448")
|
|
71
|
+
run("4 LM447")
|
|
72
|
+
run("4 LM448")
|
|
61
73
|
|
|
62
|
-
run("LM4").should
|
|
74
|
+
run("LM4").should have(2).parts
|
|
63
75
|
end
|
|
64
76
|
|
|
65
77
|
it "should not fault when not found" do
|
|
66
|
-
run("DUNNO").should
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "should export txt file" do
|
|
70
|
-
Time.should_receive(:now).and_return(Time.at(1291879432))
|
|
71
|
-
run("4 LM448").should eql("Done. 4x LM448")
|
|
72
|
-
run("txt").should eql("File saved! my_stockr_10-12-09-05-23-52.txt")
|
|
78
|
+
run("DUNNO").should be_nil
|
|
73
79
|
end
|
|
74
80
|
|
|
75
|
-
it "should export to html file" do
|
|
76
|
-
end
|
|
77
81
|
|
|
78
82
|
end
|
data/stockr.gemspec
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Generated by jeweler
|
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
|
+
# -*- encoding: utf-8 -*-
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = %q{stockr}
|
|
8
|
+
s.version = "0.2.0"
|
|
9
|
+
|
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
|
+
s.authors = ["Marcos Piccinini"]
|
|
12
|
+
s.date = %q{2010-12-11}
|
|
13
|
+
s.default_executable = %q{stockr}
|
|
14
|
+
s.description = %q{Help keep track of stuff (good for electronics)}
|
|
15
|
+
s.email = %q{x@nofxx.com}
|
|
16
|
+
s.executables = ["stockr"]
|
|
17
|
+
s.extra_rdoc_files = [
|
|
18
|
+
"README.rdoc"
|
|
19
|
+
]
|
|
20
|
+
s.files = [
|
|
21
|
+
".document",
|
|
22
|
+
".rspec",
|
|
23
|
+
"Gemfile",
|
|
24
|
+
"Gemfile.lock",
|
|
25
|
+
"README.rdoc",
|
|
26
|
+
"Rakefile",
|
|
27
|
+
"VERSION",
|
|
28
|
+
"bin/stockr",
|
|
29
|
+
"lib/stockr.rb",
|
|
30
|
+
"lib/stockr/assets/bundle.js",
|
|
31
|
+
"lib/stockr/export.rb",
|
|
32
|
+
"lib/stockr/import.rb",
|
|
33
|
+
"lib/stockr/part.rb",
|
|
34
|
+
"lib/stockr/store.rb",
|
|
35
|
+
"lib/stockr/web.rb",
|
|
36
|
+
"spec/data/export.txt",
|
|
37
|
+
"spec/spec_helper.rb",
|
|
38
|
+
"spec/stockr/export_spec.rb",
|
|
39
|
+
"spec/stockr/part_spec.rb",
|
|
40
|
+
"spec/stockr_spec.rb"
|
|
41
|
+
]
|
|
42
|
+
s.homepage = %q{http://github.com/nofxx/stockr}
|
|
43
|
+
s.licenses = ["MIT"]
|
|
44
|
+
s.require_paths = ["lib"]
|
|
45
|
+
s.rubygems_version = %q{1.3.7}
|
|
46
|
+
s.summary = %q{Keep track of all your stuff}
|
|
47
|
+
s.test_files = [
|
|
48
|
+
"spec/spec_helper.rb",
|
|
49
|
+
"spec/stockr/export_spec.rb",
|
|
50
|
+
"spec/stockr/part_spec.rb",
|
|
51
|
+
"spec/stockr_spec.rb"
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
if s.respond_to? :specification_version then
|
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
56
|
+
s.specification_version = 3
|
|
57
|
+
|
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
59
|
+
s.add_runtime_dependency(%q<redis>, [">= 0"])
|
|
60
|
+
s.add_runtime_dependency(%q<eletro>, [">= 0"])
|
|
61
|
+
s.add_runtime_dependency(%q<multipart-post>, [">= 0"])
|
|
62
|
+
s.add_development_dependency(%q<sinatra>, [">= 0"])
|
|
63
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.1.0"])
|
|
64
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
|
65
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
|
66
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
|
67
|
+
else
|
|
68
|
+
s.add_dependency(%q<redis>, [">= 0"])
|
|
69
|
+
s.add_dependency(%q<eletro>, [">= 0"])
|
|
70
|
+
s.add_dependency(%q<multipart-post>, [">= 0"])
|
|
71
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
|
72
|
+
s.add_dependency(%q<rspec>, ["~> 2.1.0"])
|
|
73
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
|
74
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
|
75
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
|
76
|
+
end
|
|
77
|
+
else
|
|
78
|
+
s.add_dependency(%q<redis>, [">= 0"])
|
|
79
|
+
s.add_dependency(%q<eletro>, [">= 0"])
|
|
80
|
+
s.add_dependency(%q<multipart-post>, [">= 0"])
|
|
81
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
|
82
|
+
s.add_dependency(%q<rspec>, ["~> 2.1.0"])
|
|
83
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
|
84
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
|
85
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
metadata
CHANGED
|
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
|
4
4
|
prerelease: false
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
|
-
-
|
|
7
|
+
- 2
|
|
8
8
|
- 0
|
|
9
|
-
version: 0.
|
|
9
|
+
version: 0.2.0
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Marcos Piccinini
|
|
@@ -14,7 +14,7 @@ autorequire:
|
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
16
|
|
|
17
|
-
date: 2010-12-
|
|
17
|
+
date: 2010-12-11 00:00:00 -02:00
|
|
18
18
|
default_executable: stockr
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|
|
@@ -31,7 +31,7 @@ dependencies:
|
|
|
31
31
|
prerelease: false
|
|
32
32
|
version_requirements: *id001
|
|
33
33
|
- !ruby/object:Gem::Dependency
|
|
34
|
-
name:
|
|
34
|
+
name: eletro
|
|
35
35
|
requirement: &id002 !ruby/object:Gem::Requirement
|
|
36
36
|
none: false
|
|
37
37
|
requirements:
|
|
@@ -40,70 +40,83 @@ dependencies:
|
|
|
40
40
|
segments:
|
|
41
41
|
- 0
|
|
42
42
|
version: "0"
|
|
43
|
-
type: :
|
|
43
|
+
type: :runtime
|
|
44
44
|
prerelease: false
|
|
45
45
|
version_requirements: *id002
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
|
-
name:
|
|
47
|
+
name: multipart-post
|
|
48
48
|
requirement: &id003 !ruby/object:Gem::Requirement
|
|
49
49
|
none: false
|
|
50
50
|
requirements:
|
|
51
|
-
- -
|
|
51
|
+
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
segments:
|
|
54
|
-
- 2
|
|
55
|
-
- 1
|
|
56
54
|
- 0
|
|
57
|
-
version:
|
|
58
|
-
type: :
|
|
55
|
+
version: "0"
|
|
56
|
+
type: :runtime
|
|
59
57
|
prerelease: false
|
|
60
58
|
version_requirements: *id003
|
|
61
59
|
- !ruby/object:Gem::Dependency
|
|
62
|
-
name:
|
|
60
|
+
name: sinatra
|
|
63
61
|
requirement: &id004 !ruby/object:Gem::Requirement
|
|
64
62
|
none: false
|
|
65
63
|
requirements:
|
|
66
|
-
- -
|
|
64
|
+
- - ">="
|
|
67
65
|
- !ruby/object:Gem::Version
|
|
68
66
|
segments:
|
|
69
|
-
- 1
|
|
70
|
-
- 0
|
|
71
67
|
- 0
|
|
72
|
-
version:
|
|
68
|
+
version: "0"
|
|
73
69
|
type: :development
|
|
74
70
|
prerelease: false
|
|
75
71
|
version_requirements: *id004
|
|
76
72
|
- !ruby/object:Gem::Dependency
|
|
77
|
-
name:
|
|
73
|
+
name: rspec
|
|
78
74
|
requirement: &id005 !ruby/object:Gem::Requirement
|
|
79
75
|
none: false
|
|
80
76
|
requirements:
|
|
81
77
|
- - ~>
|
|
82
78
|
- !ruby/object:Gem::Version
|
|
83
79
|
segments:
|
|
80
|
+
- 2
|
|
84
81
|
- 1
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
version: 1.5.1
|
|
82
|
+
- 0
|
|
83
|
+
version: 2.1.0
|
|
88
84
|
type: :development
|
|
89
85
|
prerelease: false
|
|
90
86
|
version_requirements: *id005
|
|
91
87
|
- !ruby/object:Gem::Dependency
|
|
92
|
-
name:
|
|
88
|
+
name: bundler
|
|
93
89
|
requirement: &id006 !ruby/object:Gem::Requirement
|
|
94
90
|
none: false
|
|
95
91
|
requirements:
|
|
96
|
-
- -
|
|
92
|
+
- - ~>
|
|
97
93
|
- !ruby/object:Gem::Version
|
|
98
94
|
segments:
|
|
95
|
+
- 1
|
|
99
96
|
- 0
|
|
100
|
-
|
|
97
|
+
- 0
|
|
98
|
+
version: 1.0.0
|
|
101
99
|
type: :development
|
|
102
100
|
prerelease: false
|
|
103
101
|
version_requirements: *id006
|
|
104
102
|
- !ruby/object:Gem::Dependency
|
|
105
|
-
name:
|
|
103
|
+
name: jeweler
|
|
106
104
|
requirement: &id007 !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ~>
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
segments:
|
|
110
|
+
- 1
|
|
111
|
+
- 5
|
|
112
|
+
- 1
|
|
113
|
+
version: 1.5.1
|
|
114
|
+
type: :development
|
|
115
|
+
prerelease: false
|
|
116
|
+
version_requirements: *id007
|
|
117
|
+
- !ruby/object:Gem::Dependency
|
|
118
|
+
name: rcov
|
|
119
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
|
107
120
|
none: false
|
|
108
121
|
requirements:
|
|
109
122
|
- - ">="
|
|
@@ -111,9 +124,9 @@ dependencies:
|
|
|
111
124
|
segments:
|
|
112
125
|
- 0
|
|
113
126
|
version: "0"
|
|
114
|
-
type: :
|
|
127
|
+
type: :development
|
|
115
128
|
prerelease: false
|
|
116
|
-
version_requirements: *
|
|
129
|
+
version_requirements: *id008
|
|
117
130
|
description: Help keep track of stuff (good for electronics)
|
|
118
131
|
email: x@nofxx.com
|
|
119
132
|
executables:
|
|
@@ -121,14 +134,12 @@ executables:
|
|
|
121
134
|
extensions: []
|
|
122
135
|
|
|
123
136
|
extra_rdoc_files:
|
|
124
|
-
- LICENSE.txt
|
|
125
137
|
- README.rdoc
|
|
126
138
|
files:
|
|
127
139
|
- .document
|
|
128
140
|
- .rspec
|
|
129
141
|
- Gemfile
|
|
130
142
|
- Gemfile.lock
|
|
131
|
-
- LICENSE.txt
|
|
132
143
|
- README.rdoc
|
|
133
144
|
- Rakefile
|
|
134
145
|
- VERSION
|
|
@@ -136,12 +147,16 @@ files:
|
|
|
136
147
|
- lib/stockr.rb
|
|
137
148
|
- lib/stockr/assets/bundle.js
|
|
138
149
|
- lib/stockr/export.rb
|
|
150
|
+
- lib/stockr/import.rb
|
|
139
151
|
- lib/stockr/part.rb
|
|
140
152
|
- lib/stockr/store.rb
|
|
141
153
|
- lib/stockr/web.rb
|
|
154
|
+
- spec/data/export.txt
|
|
142
155
|
- spec/spec_helper.rb
|
|
156
|
+
- spec/stockr/export_spec.rb
|
|
143
157
|
- spec/stockr/part_spec.rb
|
|
144
158
|
- spec/stockr_spec.rb
|
|
159
|
+
- stockr.gemspec
|
|
145
160
|
has_rdoc: true
|
|
146
161
|
homepage: http://github.com/nofxx/stockr
|
|
147
162
|
licenses:
|
|
@@ -156,7 +171,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
156
171
|
requirements:
|
|
157
172
|
- - ">="
|
|
158
173
|
- !ruby/object:Gem::Version
|
|
159
|
-
hash: -
|
|
174
|
+
hash: -51961578438735344
|
|
160
175
|
segments:
|
|
161
176
|
- 0
|
|
162
177
|
version: "0"
|
|
@@ -177,5 +192,6 @@ specification_version: 3
|
|
|
177
192
|
summary: Keep track of all your stuff
|
|
178
193
|
test_files:
|
|
179
194
|
- spec/spec_helper.rb
|
|
195
|
+
- spec/stockr/export_spec.rb
|
|
180
196
|
- spec/stockr/part_spec.rb
|
|
181
197
|
- spec/stockr_spec.rb
|
data/LICENSE.txt
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2010 Marcos Piccinini
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
-
a copy of this software and associated documentation files (the
|
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
-
the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
|
12
|
-
included in all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|