oldness 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .idea
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem 'rspec'
4
+ gem 'thor'
data/bin/oldness ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/../lib/')
4
+
5
+ require 'oldness'
6
+
7
+ # todo: detect pluralization?
8
+ Oldness::CLI.start
9
+
data/config.ru ADDED
@@ -0,0 +1,2 @@
1
+ require './api'
2
+ run Sinatra::Application
@@ -0,0 +1,37 @@
1
+ require 'thor'
2
+
3
+ module Oldness
4
+
5
+ class CLI < Thor
6
+
7
+ desc "rate MEDIUM DATE", "give a star rating of oldness for a work in MEDIUM made on DATE"
8
+ def rate(medium, date)
9
+ print "#{get_class(medium).rate(date, :formatted => true)}\n"
10
+ end
11
+ map "rating" => "rate"
12
+
13
+ desc "ranges MEDIUM", "show what dates fall under what star ratings for a work in MEDIUM"
14
+ def ranges(medium)
15
+ print "#{get_class(medium).ranges(:formatted=>true)}\n"
16
+ end
17
+ map "range" => "ranges"
18
+
19
+ desc "first MEDIUM", "print the first work in MEDIUM"
20
+ def first(medium)
21
+ print "#{get_class(medium).first}\n"
22
+ end
23
+
24
+ desc "media", "List what mediums can be used in other commands"
25
+ def media
26
+ print Oldness::media.collect(&:to_s).sort.inject("") { |l, c| l + c.sub("Oldness::", "")+"\n"}.downcase
27
+ end
28
+ map "mediums" => "media"
29
+ map "list" => "media"
30
+
31
+ no_tasks do
32
+ def get_class(medium)
33
+ eval("Oldness::" + medium.split('-').collect(&:capitalize).inject(:+))
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,119 @@
1
+ require 'date'
2
+ require 'oldness/work'
3
+
4
+ module Oldness
5
+ def self.media
6
+ list = []
7
+ ObjectSpace.each_object(Class) do |c|
8
+ next unless c.superclass == Medium
9
+ list << c
10
+ end
11
+ list
12
+ end
13
+
14
+ class Medium
15
+ def self.ranges(args={})
16
+ current_date = args[:when] ? args[:when] : Date.today
17
+ span = (current_date-first.date)
18
+ unit = span/81
19
+ ranges = {5 => (first.date..current_date-27*unit),
20
+ 4 => (current_date-27*unit..current_date-9*unit),
21
+ 3 => (current_date-9*unit..current_date-3*unit),
22
+ 2 => (current_date-3*unit..current_date-unit),
23
+ 1 => (current_date-unit..current_date)}
24
+ if args[:formatted]
25
+ f_ranges = ""
26
+ ranges.each do |stars, range|
27
+ f_ranges += ("*" * stars) + (" " * (5-stars)) + ": #{range}\n"
28
+ end
29
+ f_ranges.chomp
30
+ else
31
+ ranges
32
+ end
33
+ end
34
+
35
+ def self.rate(work_date, args={})
36
+ work_date = parse_date(work_date)
37
+
38
+ formatted = args[:formatted]
39
+ args[:formatted] = nil
40
+ rating = ranges(args).find {|key, range| range.cover?(work_date)}[0]
41
+
42
+ if formatted
43
+ "*" * rating
44
+ else
45
+ rating
46
+ end
47
+ end
48
+
49
+ def self.began(date, args={})
50
+ @first = Work.new(date, :title => args[:with], :by => args[:by])
51
+ def self.first
52
+ @first
53
+ end
54
+ end
55
+
56
+ private
57
+ def self.parse_date(date)
58
+ begin
59
+ date_info = date.split("-")
60
+ rescue NoMethodError
61
+ return date
62
+ end
63
+
64
+ if date_info[0].downcase.end_with?('bc')
65
+ date_info[0][-2..-1] = ""
66
+ date_info[0].insert(0,'-')
67
+ end
68
+
69
+ Date.new(*date_info.map {|v| v.to_i})
70
+ end
71
+ end
72
+
73
+ class Literature < Medium
74
+ began Date.new(-1300), :with => "The Epic of Gilgamesh"
75
+ end
76
+
77
+ class Philosophy < Medium
78
+ began Date.new(-800), :with => "The Upanishads"
79
+ end
80
+ Religion = Philosophy # now that's what I call opinionated software
81
+
82
+ class SciFi < Medium
83
+ began Date.new(1620), :with => "Somnium", :by => "Johannes Kepler"
84
+ end
85
+
86
+ class Novel < Medium
87
+ began Date.new(1010), :with => "Tale of Genji", :by => "Murasaki Shikibu"
88
+ end
89
+ Book = Novel
90
+
91
+ class Film < Medium
92
+ began Date.new(1894, 2, 5), :by => "Jean Le Roy"
93
+ end
94
+ Movie = Film
95
+
96
+ class Comic < Medium
97
+ began Date.new(1837), :with => "Histoire de M. Vieux Bois", :by => "Rodolphe Topffer" # todo: Töpffer
98
+ end
99
+ Manga = Comic
100
+
101
+ class Videogame < Medium
102
+ began Date.new(1951, 5, 4), :with => "Nimrod", :by => "Ferranti International plc"
103
+ end
104
+
105
+ class History < Medium
106
+ began Date.new(-411), :with => "History of the Pelopnnesian War", :by => "Thucydides"
107
+ end
108
+
109
+ class Animation < Medium
110
+ began Date.new(1906, 4, 6), :with => "Humorous Phases of Funny Faces", :by => "J. Stuart Blackton"
111
+ end
112
+ Cartoon = Animation
113
+ Anime = Animation
114
+
115
+ class Rpg < Medium
116
+ began Date.new(1974), :with => "Dungeons & Dragons", :by => "Gary Gygax and David Arneson"
117
+ end
118
+
119
+ end
@@ -0,0 +1,3 @@
1
+ module Oldness
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,32 @@
1
+ module Oldness
2
+ class Work
3
+ def by
4
+ @by ? @by : "Unknown"
5
+ end
6
+ def title
7
+ @title ? @title : "Untitled"
8
+ end
9
+ attr_accessor :date
10
+ def initialize(date, args={})
11
+ @date, @title, @by = date, args[:title], args[:by]
12
+ end
13
+ def to_s
14
+ if date.yday == 1
15
+ if date.year < 0
16
+ f_date = (date.year * -1).to_s + "BC"
17
+ else
18
+ f_date = "#{date.year}"
19
+ end
20
+ elsif date.mday == 1
21
+ f_date = date.strftime("%B %Y")
22
+ else
23
+ f_date = date.strftime("%B %-d, %Y")
24
+ end
25
+ str = "#{title} (#{f_date})"
26
+ if @by
27
+ str += ", by #{@by}"
28
+ end
29
+ str
30
+ end
31
+ end
32
+ end
data/lib/oldness.rb ADDED
@@ -0,0 +1,2 @@
1
+ require_relative 'oldness/cli'
2
+ require_relative 'oldness/medium'
data/oldness.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require 'oldness/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'oldness'
6
+ s.version = Oldness::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.date = '2011-12-20'
9
+ s.authors = ['Nick Novitski']
10
+ s.email = 'nicknovitski@gmail.com'
11
+ s.homepage = 'http://github.com/njay/oldness'
12
+ s.summary = 'Instant historical perspective'
13
+ s.description = 'A library and shell command that rates the age of different types of things on a five-star system'
14
+
15
+ s.required_rubygems_version = '>= 1.3.7'
16
+ s.specification_version = 3
17
+
18
+ ignores = File.readlines(".gitignore").grep(/\S+/).map {|s| s.chomp }
19
+ dotfiles = [".gitignore"]
20
+
21
+ s.files = Dir["**/*"].reject {|f| File.directory?(f) || ignores.any? {|i| File.fnmatch(i, f) } } + dotfiles
22
+ s.test_files = s.files.grep(/^spec\//)
23
+ s.require_paths = ['lib']
24
+ s.executables = ['oldness']
25
+
26
+ s.add_development_dependency 'rspec'
27
+ s.add_development_dependency 'bundler'
28
+ s.add_dependency 'thor', '~> 0.14'
29
+ end
Binary file
data/readme.markdown ADDED
@@ -0,0 +1,65 @@
1
+ # oldness
2
+
3
+ Oldness is a library and shell command that places the age of a published work on a semi-arbitrary five-star scale.
4
+
5
+ ## Installation
6
+
7
+ gem install oldness
8
+
9
+ require 'oldness'
10
+
11
+ ## Usage
12
+
13
+ ### CLI
14
+
15
+ $ oldness list
16
+ animation
17
+ comic
18
+ film
19
+ history
20
+ literature
21
+ novel
22
+ philosophy
23
+ rpg
24
+ scifi
25
+ videogame
26
+ $ oldness rate comic 1987-10
27
+ ****
28
+ $ oldness ranges movie
29
+ *****: 1894-02-05..1972-09-14
30
+ **** : 1972-09-14..1998-11-27
31
+ *** : 1998-11-27..2007-08-22
32
+ ** : 2007-08-22..2010-07-21
33
+ * : 2010-07-21..2012-01-04
34
+ $ oldness first philosophy
35
+ Tale of Genji (1010), by Murasaki Shikibu
36
+
37
+ ### Library
38
+
39
+ Declaring the existence of a medium is easy; you don't need a national reputation as a culture critic or scholar.
40
+
41
+ class Rubies < Medium
42
+ began Date.new(1979)
43
+ end
44
+
45
+ Although of course it would be better if you could point to a particular work that you saw as kicking things off.
46
+
47
+ class RockNRoll < Medium
48
+ began Date.new(1944), :with => "Strange Things Happen Every Day", :by => "Sister Rosetta Tharpe"
49
+ end
50
+
51
+ Mediums know how to rate by date.
52
+
53
+ Rubies.rate(Date.new(2010, 8, 29)) # => 3
54
+ Rubies.rate("2012-1-4") # => 1
55
+
56
+ They also know what dates fall under what ratings.
57
+
58
+ Rubies.ranges[5] #=> #<Date: 1979-01-01>..#<Date: 2001-01-02>
59
+
60
+ And, if you've told them, they remember their roots.
61
+
62
+ RockNRoll.first.title #=> "Strange Things Happen Every Day"
63
+ Rubies.first.by #=> "Unknown"
64
+
65
+ Just a reminder: mediums are timeless, so they never need to be instantiated.
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ module Oldness
4
+ describe "oldness" do
5
+ before :all do
6
+ Dir.chdir("../bin")
7
+ end
8
+
9
+ describe "rating" do
10
+ it "calls the rating method of the named Medium class with :formatted=>true"
11
+ end
12
+
13
+ describe "range" do
14
+ it "calls the range method of the named Medium class with :formatted=>true"
15
+ end
16
+
17
+ describe "first" do
18
+ it "prints the string formatting of the Work object stored under the first method of the appropriate Medium class"
19
+ end
20
+
21
+ describe "media" do
22
+ it "lists all subclasses of Medium in the object space" do
23
+ list = []
24
+ ObjectSpace.each_object(Class) do |c|
25
+ next unless c.superclass == Medium
26
+ list << c
27
+ end
28
+ `./oldness media`.should == list.collect(&:to_s).sort.inject("") { |l, c| l + c.downcase.sub("oldness::", "")+"\n" }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ module Oldness
4
+ describe Medium do
5
+ def ranges_for(start_date, current_date = Date.today)
6
+ span = (current_date-start_date)
7
+ unit = span/81
8
+ {5 => (start_date..current_date-27*unit),
9
+ 4 => (current_date-27*unit..current_date-9*unit),
10
+ 3 => (current_date-9*unit..current_date-3*unit),
11
+ 2 => (current_date-3*unit..current_date-unit),
12
+ 1 => (current_date-unit..current_date)}
13
+ end
14
+ def rating_for(start_date, work_date, current_date = Date.today)
15
+ ranges_for(start_date, current_date).find {|key, range| range.cover?(work_date)}[0]
16
+ end
17
+ before :all do
18
+ class RubyPrograms < Medium
19
+ began Date.new(1979), :with=>"Hello World", :by => "Matz"
20
+ end
21
+ @ruby_ranges = ranges_for(Date.new(1979))
22
+ end
23
+ describe ".ranges" do
24
+ it "returns a particular kind of hash" do
25
+ RubyPrograms.ranges.should == @ruby_ranges
26
+ end
27
+ it "can take an argument for a particular date" do
28
+ RubyPrograms.ranges(:when => Date.new(2009)).should == ranges_for(Date.new(1979), Date.new(2009))
29
+ end
30
+ it "can have formatted output instead" do
31
+ RubyPrograms.ranges(:formatted => true).should == "*****: #{@ruby_ranges[5]}\n**** : #{@ruby_ranges[4]}\n*** : #{@ruby_ranges[3]}\n** : #{@ruby_ranges[2]}\n* : #{@ruby_ranges[1]}"
32
+ end
33
+ end
34
+ describe ".rate" do
35
+ it "rates oldest possible things as fives" do
36
+ RubyPrograms.rate(Date.new(1979)).should == 5
37
+ end
38
+ it "rates newest possible things as ones" do
39
+ RubyPrograms.rate(Date.today).should == 1
40
+ end
41
+ it "rates everything else properly" do
42
+ [Date.new(2001), Date.new(2008), Date.new(2010)].each do |date|
43
+ RubyPrograms.rate(date).should == rating_for(Date.new(1979), date)
44
+ end
45
+ end
46
+ it "can take an argument for a particular date" do
47
+ RubyPrograms.rate(Date.new(2010), :when => Date.new(2050)).should == 5
48
+ end
49
+ it "can have formatted output instead" do
50
+ RubyPrograms.rate(Date.today, :formatted=>true).should == "*"
51
+ RubyPrograms.rate(Date.new(2010), :when => Date.new(2050), :formatted => true).should == "*****"
52
+ end
53
+ end
54
+ describe ".first" do
55
+ it "returns a Work object with the attributes passed to .began" do
56
+ RubyPrograms.first.title.should == "Hello World"
57
+ RubyPrograms.first.by.should == "Matz"
58
+ RubyPrograms.first.date.should == Date.new(1979)
59
+ RubyPrograms.first.to_s.should == "Hello World (1979), by Matz"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require_relative '../lib/oldness'
3
+ require 'date'
data/spec/work_spec.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ module Oldness
4
+ describe Work do
5
+ context "BC, year only, no title, no credit" do
6
+ let(:w) {Work.new(Date.new(-1000))}
7
+ describe "#date" do
8
+ it "returns the date object" do
9
+ w.date.should == Date.new(-1000)
10
+ end
11
+ end
12
+ describe "#by" do
13
+ it "defaults to 'Unknown'" do
14
+ w.by.should == "Unknown"
15
+ end
16
+ end
17
+ describe "#title" do
18
+ it "defaults to 'Untitled'" do
19
+ w.title.should == "Untitled"
20
+ end
21
+ end
22
+ describe "#to_s" do
23
+ it "Uses 'BC' instead of negative years" do
24
+ "#{w}".should == "Untitled (1000BC)"
25
+ end
26
+ end
27
+ end
28
+ context "Year and Month, Title, no author" do
29
+ let(:w) {Work.new(Date.new(1974, 2), :title => "Dungeons and Dragons")}
30
+ describe "#to_s" do
31
+ it "formats the month as a word" do
32
+ "#{w}".should == "Dungeons and Dragons (February 1974)"
33
+ end
34
+ end
35
+ end
36
+ context "Year, month and day, title and author" do
37
+ let(:w) {Work.new(Date.new(1906, 4, 6), :title => "Humorous Phases of Funny Faces", :by => "J. Stuart Blackton")}
38
+ describe "#to_s" do
39
+ it "includes the day of the month" do
40
+ "#{w}".should == "#{w.title} (April 6, 1906), by #{w.by}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ end
data/tasks.thor ADDED
@@ -0,0 +1,98 @@
1
+
2
+ class Gems < Thor
3
+ desc "validate", "Test gemspec"
4
+ def validate
5
+ raise Exception unless gemspec.validate
6
+ end
7
+
8
+ desc "build", "Build gem locally"
9
+ def build
10
+ invoke :validate
11
+ system "gem build #{gemspec.name}.gemspec"
12
+ FileUtils.mkdir_p "pkg"
13
+ FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg"
14
+ end
15
+
16
+ desc "clean", "Delete generated gem files"
17
+ def clean
18
+ FileUtils.rm_rf "pkg"
19
+ end
20
+
21
+ desc "install", "Build and install gem locally"
22
+ def install
23
+ invoke :build
24
+ system "gem install pkg/#{gemspec.name}-#{gemspec.version}"
25
+ end
26
+
27
+ no_tasks do
28
+ def gemspec
29
+ @gemspec ||= eval(File.read(Dir["*.gemspec"].first))
30
+ end
31
+ end
32
+ end
33
+
34
+ class VersionBump < Thor
35
+ desc "manual MAJOR MINOR PATCH", "Set version number to 'MAJOR.MINOR.PATCH'"
36
+ def manual(major, minor, patch)
37
+ version[0], version[1], version[2] = major, minor, patch
38
+ update_version
39
+ end
40
+
41
+ desc "major", "Bump by a major version"
42
+ def major
43
+ version[0] += 1
44
+ version[1] = 0
45
+ version[2] = 0
46
+ update_version
47
+ end
48
+ desc "minor", "Bump by a minor version"
49
+ def minor
50
+ version[1] += 1
51
+ version[2] = 0
52
+ update_version
53
+ end
54
+ desc "patch", "Bump by a patch version"
55
+ def patch
56
+ version[2] += 1
57
+ update_version
58
+ end
59
+ no_tasks do
60
+ def version
61
+ $:.push File.expand_path("../lib", __FILE__)
62
+ require 'oldness/version'
63
+ Oldness::VERSION =~ /(\d+)\.(\d+)\.(\d+)/
64
+ @version ||= [$1.to_i, $2.to_i, $3.to_i]
65
+ end
66
+ def update_version
67
+ path = File.expand_path("./lib/oldness/version.rb")
68
+ new_source = File.read(path).sub(/VERSION\s*=.*/, %Q{VERSION = "#{version.join('.')}"})
69
+ File.open(path, 'w') { |f| f.puts new_source }
70
+ end
71
+ end
72
+ end
73
+
74
+ class Publish < Thor
75
+ desc "github", "Push changes to github"
76
+ def github
77
+ system "git push origin : --tags"
78
+ end
79
+ desc "gem", "Build gem and push it to rubygems"
80
+ def gem
81
+ confirm = ask "This will push whatever's in the working directory to rubygems. Are you SURE? Y/N"
82
+ if confirm == "Y"
83
+ invoke "gems:build"
84
+ system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
85
+ end
86
+ end
87
+ desc "all", "Push to both github and rubygems"
88
+ def all
89
+ invoke :github
90
+ invoke :gem
91
+ end
92
+
93
+ no_tasks do
94
+ def gemspec
95
+ @gemspec ||= eval(File.read(Dir["*.gemspec"].first))
96
+ end
97
+ end
98
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oldness
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Nick Novitski
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-12-20 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :development
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: bundler
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: thor
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: "0.14"
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ description: A library and shell command that rates the age of different types of things on a five-star system
49
+ email: nicknovitski@gmail.com
50
+ executables:
51
+ - oldness
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - bin/oldness
58
+ - config.ru
59
+ - Gemfile
60
+ - lib/oldness/cli.rb
61
+ - lib/oldness/medium.rb
62
+ - lib/oldness/version.rb
63
+ - lib/oldness/work.rb
64
+ - lib/oldness.rb
65
+ - oldness.gemspec
66
+ - pkg/oldness-0.0.1.gem
67
+ - readme.markdown
68
+ - spec/cli_spec.rb
69
+ - spec/medium_spec.rb
70
+ - spec/spec_helper.rb
71
+ - spec/work_spec.rb
72
+ - tasks.thor
73
+ - .gitignore
74
+ homepage: http://github.com/njay/oldness
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options: []
79
+
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 1.3.7
94
+ requirements: []
95
+
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.11
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Instant historical perspective
101
+ test_files:
102
+ - spec/cli_spec.rb
103
+ - spec/medium_spec.rb
104
+ - spec/spec_helper.rb
105
+ - spec/work_spec.rb
106
+ has_rdoc: