frecon 0.2.2 → 0.3.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.
- checksums.yaml +4 -4
- data/lib/frecon/base/bson.rb +16 -0
- data/lib/frecon/base/variables.rb +1 -1
- data/lib/frecon/base.rb +1 -0
- data/lib/frecon/controller.rb +36 -15
- data/lib/frecon/controllers/dump_controller.rb +14 -2
- data/lib/frecon/controllers/participations_controller.rb +2 -2
- data/lib/frecon/controllers/records_controller.rb +2 -2
- data/lib/frecon/controllers/robots_controller.rb +2 -2
- data/lib/frecon/match_number.rb +3 -0
- data/lib/frecon/model.rb +4 -0
- data/lib/frecon/position.rb +4 -0
- data/lib/frecon/scraper.rb +70 -0
- data/lib/frecon/scrapers.rb +10 -0
- data/lib/frecon/server.rb +1 -0
- data/lib/frecon.rb +4 -0
- metadata +18 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd60a8e39df9d65354023f15a71e7ff1941465cc
|
4
|
+
data.tar.gz: 322aad2f9008ee3bac2f566a1afcc7ccc60938f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d40ef54381e9b613289a0c1b82f486a965975866e1f7e3cbe16ec15285708e05156b2bfc4c6a27a567b3ecd72fa128f379fbcbfad6b008f5ccd19f81970b559b
|
7
|
+
data.tar.gz: e6c5a2c2bbddf8de4b04441c59cc45575f76019fb2f81e3d110860b736c8ce8a6ff57203f36d6e6f92066261b52c8b5ad18d9e8052543500d158b74f352c4df2
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# lib/frecon/base/bson.rb
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Christopher Cooper, Sam Craig, Tiger Huang, Vincent Mai, Sam Mercier, and Kristofer Rye
|
4
|
+
#
|
5
|
+
# This file is part of FReCon, an API for scouting at FRC Competitions, which is
|
6
|
+
# licensed under the MIT license. You should have received a copy of the MIT
|
7
|
+
# license with this program. If not, please see
|
8
|
+
# <http://opensource.org/licenses/MIT>.
|
9
|
+
|
10
|
+
module BSON
|
11
|
+
class ObjectId
|
12
|
+
def as_json(*args)
|
13
|
+
to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/frecon/base.rb
CHANGED
data/lib/frecon/controller.rb
CHANGED
@@ -34,44 +34,61 @@ module FReCon
|
|
34
34
|
"Could not find #{model} of #{attribute} #{value}!"
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
def self.process_json_object_request(request)
|
37
|
+
def self.process_json_request(request)
|
39
38
|
# Rewind the request body (an IO object)
|
40
39
|
# in case someone else has already played
|
41
40
|
# through it.
|
42
41
|
request.body.rewind
|
43
42
|
|
44
43
|
begin
|
45
|
-
# Parse the POST data as a JSON hash
|
46
|
-
# (because that's what it is)
|
47
44
|
post_data = JSON.parse(request.body.read)
|
48
45
|
rescue JSON::ParserError => e
|
49
|
-
# If we have malformed JSON (JSON::ParserError is
|
50
|
-
# raised), escape out of the function.
|
51
46
|
raise RequestError.new(400, e.message)
|
52
47
|
end
|
53
48
|
|
54
|
-
raise RequestError.new(422, "Must pass a JSON object!", {post_data: post_data}) if post_data.is_an?(Array)
|
55
49
|
post_data
|
56
50
|
end
|
57
51
|
|
58
52
|
def self.create(request, params, post_data = nil)
|
59
|
-
post_data ||=
|
53
|
+
post_data ||= process_json_request request
|
60
54
|
|
61
|
-
|
62
|
-
|
55
|
+
if post_data.is_an? Array
|
56
|
+
results = post_data.map do |post_data_item|
|
57
|
+
begin
|
58
|
+
self.create(nil, nil, post_data_item)
|
59
|
+
rescue RequestError => e
|
60
|
+
e.return_value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
status_code = 201
|
65
|
+
|
66
|
+
if(results.map do |result|
|
67
|
+
result.is_an?(Array) ? result[0] : 422
|
68
|
+
end.select do |status_code|
|
69
|
+
status_code != 201
|
70
|
+
end.count > 0)
|
71
|
+
|
72
|
+
status_code = 422
|
73
|
+
end
|
63
74
|
|
64
|
-
|
65
|
-
[201, @model.to_json]
|
75
|
+
[status_code, results.to_json]
|
66
76
|
else
|
67
|
-
|
77
|
+
@model = model.new
|
78
|
+
@model.attributes = post_data
|
79
|
+
|
80
|
+
if @model.save
|
81
|
+
[201, @model.to_json]
|
82
|
+
else
|
83
|
+
raise RequestError.new(422, @model.errors.full_messages, {params: params, post_data: post_data})
|
84
|
+
end
|
68
85
|
end
|
69
86
|
end
|
70
87
|
|
71
88
|
def self.update(request, params, post_data = nil)
|
72
89
|
raise RequestError.new(400, "Must supply a #{model_name.downcase} id!") unless params[:id]
|
73
90
|
|
74
|
-
post_data ||=
|
91
|
+
post_data ||= process_json_request request
|
75
92
|
|
76
93
|
@model = find_model params
|
77
94
|
|
@@ -127,6 +144,8 @@ module FReCon
|
|
127
144
|
end
|
128
145
|
|
129
146
|
def self.team_number_to_team_id(post_data)
|
147
|
+
return post_data unless post_data.is_a?(Hash)
|
148
|
+
|
130
149
|
if post_data["team_number"] && !post_data["team_id"]
|
131
150
|
unless (team = Team.number post_data["team_number"]).nil?
|
132
151
|
post_data["team_id"] = team.id
|
@@ -143,6 +162,8 @@ module FReCon
|
|
143
162
|
# This supports match_number and competition_name
|
144
163
|
# or match_number and competition (which is a Hash).
|
145
164
|
def self.match_number_and_competition_to_match_id(post_data)
|
165
|
+
return post_data unless post_data.is_a?(Hash)
|
166
|
+
|
146
167
|
if post_data["match_number"] && !post_data["match_id"]
|
147
168
|
if post_data["competition_name"] && (competition = Competition.find_by name: post_data["competition_name"])
|
148
169
|
# Try to set the match to the already existing match.
|
@@ -165,7 +186,7 @@ module FReCon
|
|
165
186
|
post_data.delete("competition_name")
|
166
187
|
|
167
188
|
post_data
|
168
|
-
elsif post_data["competition"] && post_data["competition"]["_id"] &&
|
189
|
+
elsif post_data["competition"] && post_data["competition"]["_id"] && (competition = Competition.find_by(id: post_data["competition"]["_id"]))
|
169
190
|
# Try to set the match to the already existing match.
|
170
191
|
match = competition.matches.find_by number: post_data["match_number"]
|
171
192
|
|
@@ -15,11 +15,23 @@ module FReCon
|
|
15
15
|
def self.full(params)
|
16
16
|
dump = {}
|
17
17
|
|
18
|
-
Model.descendants.
|
19
|
-
|
18
|
+
ordered_descendants = Model.descendants.sort_by do |model|
|
19
|
+
id_fields = model.fields.keys.select do |attribute|
|
20
|
+
attribute.ends_with?("_id") && attribute != "_id"
|
21
|
+
end
|
22
|
+
|
23
|
+
[id_fields.count, dump_compliant_name(model)]
|
24
|
+
end
|
25
|
+
|
26
|
+
ordered_descendants.each do |child|
|
27
|
+
dump[dump_compliant_name(child)] = child.all
|
20
28
|
end
|
21
29
|
|
22
30
|
dump.to_json
|
23
31
|
end
|
32
|
+
|
33
|
+
def self.dump_compliant_name(model)
|
34
|
+
model.name.gsub(/FReCon::/, "").downcase.pluralize
|
35
|
+
end
|
24
36
|
end
|
25
37
|
end
|
@@ -9,8 +9,8 @@
|
|
9
9
|
|
10
10
|
module FReCon
|
11
11
|
class ParticipationsController < Controller
|
12
|
-
def self.create(request, params)
|
13
|
-
super(request, params, team_number_to_team_id(
|
12
|
+
def self.create(request, params, post_data = nil)
|
13
|
+
super(request, params, post_data || team_number_to_team_id(process_json_request(request)))
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.competition(params)
|
@@ -13,8 +13,8 @@ require "frecon/models"
|
|
13
13
|
|
14
14
|
module FReCon
|
15
15
|
class RecordsController < Controller
|
16
|
-
def self.create(request, params)
|
17
|
-
super(request, params, match_number_and_competition_to_match_id(team_number_to_team_id(
|
16
|
+
def self.create(request, params, post_data = nil)
|
17
|
+
super(request, params, post_data || match_number_and_competition_to_match_id(team_number_to_team_id(process_json_request(request))))
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.competition(params)
|
@@ -12,8 +12,8 @@ require "frecon/models/robot"
|
|
12
12
|
|
13
13
|
module FReCon
|
14
14
|
class RobotsController < Controller
|
15
|
-
def self.create(request, params)
|
16
|
-
super(request, params, team_number_to_team_id(
|
15
|
+
def self.create(request, params, post_data = nil)
|
16
|
+
super(request, params, post_data || team_number_to_team_id(process_json_request(request)))
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.competition(params)
|
data/lib/frecon/match_number.rb
CHANGED
@@ -125,6 +125,9 @@ module FReCon
|
|
125
125
|
# round (Integer), optional
|
126
126
|
# replay_number (Integer), optional
|
127
127
|
|
128
|
+
# Convert keys to symbols if needed.
|
129
|
+
args = Hash[args.map { |key, value| [key.to_sym, value] }]
|
130
|
+
|
128
131
|
raise TypeError, "type must be a Symbol or String" unless args[:type].is_a?(Symbol) || args[:type].is_a?(String)
|
129
132
|
raise ArgumentError, "type must be in #{POSSIBLE_TYPES.inspect}" unless POSSIBLE_TYPES.include?(args[:type].to_sym)
|
130
133
|
|
data/lib/frecon/model.rb
CHANGED
@@ -26,6 +26,10 @@ module FReCon
|
|
26
26
|
ObjectSpace.each_object(Class).select { |possibleChild| possibleChild < self }
|
27
27
|
end
|
28
28
|
|
29
|
+
def self.controller
|
30
|
+
(self.name.pluralize + "Controller").constantize
|
31
|
+
end
|
32
|
+
|
29
33
|
def no_invalid_relations
|
30
34
|
# Get all of the belongs_to fields (ends with "_id" and not "_id" because that is the id).
|
31
35
|
attributes.keys.select { |attribute| attribute.end_with?("_id") && attribute != "_id" }.each do |relation|
|
data/lib/frecon/position.rb
CHANGED
@@ -31,6 +31,8 @@ module FReCon
|
|
31
31
|
when String
|
32
32
|
Position.new(object).mongoize
|
33
33
|
when Hash
|
34
|
+
# Convert keys to symbols if necessary.
|
35
|
+
object = Hash[object.map { |key, value| [key.to_sym, value] }]
|
34
36
|
Position.new(object[:alliance], object[:number]).mongoize
|
35
37
|
else
|
36
38
|
object
|
@@ -45,6 +47,8 @@ module FReCon
|
|
45
47
|
when String
|
46
48
|
Position.new(object).mongoize
|
47
49
|
when Hash
|
50
|
+
# Convert keys to symbols if necessary.
|
51
|
+
object = Hash[object.map { |key, value| [key.to_sym, value] }]
|
48
52
|
Position.new(object[:alliance], object[:number]).mongoize
|
49
53
|
else
|
50
54
|
object
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# lib/frecon/scraper.rb
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Christopher Cooper, Sam Craig, Tiger Huang, Vincent Mai, Sam Mercier, and Kristofer Rye
|
4
|
+
#
|
5
|
+
# This file is part of FReCon, an API for scouting at FRC Competitions, which is
|
6
|
+
# licensed under the MIT license. You should have received a copy of the MIT
|
7
|
+
# license with this program. If not, please see
|
8
|
+
# <http://opensource.org/licenses/MIT>.
|
9
|
+
|
10
|
+
require "httparty"
|
11
|
+
|
12
|
+
module FReCon
|
13
|
+
# The default scraper scrapes other FReCon instances.
|
14
|
+
# To scrape a different source, a descendant scraper should be used.
|
15
|
+
class Scraper
|
16
|
+
def initialize(base_uri)
|
17
|
+
@base_uri = base_uri
|
18
|
+
end
|
19
|
+
|
20
|
+
# Reads and imports a data string.
|
21
|
+
# Determines what to do with information in the `context` hash.
|
22
|
+
def read(data, context = {})
|
23
|
+
# `data` will be a string, so we need to convert it from JSON.
|
24
|
+
data = JSON.parse(data)
|
25
|
+
|
26
|
+
# Here we want `context` to tell us what model we are making.
|
27
|
+
if context[:model]
|
28
|
+
result = context[:model].controller.create(nil, nil, data)
|
29
|
+
result.first == 201 ? result.first : JSON.parse(result.last)
|
30
|
+
else
|
31
|
+
# Therefore, we must be dealing with a dump.
|
32
|
+
statuses = data.map do |key, value|
|
33
|
+
begin
|
34
|
+
unless value.empty?
|
35
|
+
model = ("FReCon::" + key.singularize.capitalize).constantize
|
36
|
+
result = model.controller.create(nil, nil, value)
|
37
|
+
result.first == 201 ? result.first : JSON.parse(result.last)
|
38
|
+
end
|
39
|
+
rescue Moped::Errors::OperationFailure => e
|
40
|
+
RequestError.new(422, "A model already exists in your database with the key you are trying to import.\nPerhaps you should clear your database?").return_value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
statuses.delete(nil)
|
44
|
+
statuses
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# If no arguments are passed, will import the whole other database.
|
49
|
+
# If only one argument is passed, will import all of that model.
|
50
|
+
# If two arguments are passed, will import the models that match
|
51
|
+
# the query params.
|
52
|
+
def get(model = nil, query = {})
|
53
|
+
# Turns something like "team" into Team.
|
54
|
+
model = ("FReCon::" + model.capitalize).constantize if model.is_a?(String)
|
55
|
+
|
56
|
+
# The route name for the model branch.
|
57
|
+
route_name = model.name.gsub(/FReCon::/, "").downcase.pluralize if model
|
58
|
+
|
59
|
+
if !model && query.empty?
|
60
|
+
data = HTTParty.get("http://#{@base_uri}:4567/dump")
|
61
|
+
elsif model && query.empty?
|
62
|
+
data = HTTParty.get("http://#{@base_uri}:4567/#{route_name}")
|
63
|
+
else
|
64
|
+
data = HTTParty.get("http://#{@base_uri}:4567/#{route_name}", { query: query })
|
65
|
+
end
|
66
|
+
|
67
|
+
read data.body, model: model
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# lib/frecon/scrapers.rb
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Christopher Cooper, Sam Craig, Tiger Huang, Vincent Mai, Sam Mercier, and Kristofer Rye
|
4
|
+
#
|
5
|
+
# This file is part of FReCon, an API for scouting at FRC Competitions, which is
|
6
|
+
# licensed under the MIT license. You should have received a copy of the MIT
|
7
|
+
# license with this program. If not, please see
|
8
|
+
# <http://opensource.org/licenses/MIT>.
|
9
|
+
|
10
|
+
require "frecon/scraper"
|
data/lib/frecon/server.rb
CHANGED
data/lib/frecon.rb
CHANGED
@@ -7,8 +7,12 @@
|
|
7
7
|
# license with this program. If not, please see
|
8
8
|
# <http://opensource.org/licenses/MIT>.
|
9
9
|
|
10
|
+
require "mongoid"
|
11
|
+
|
10
12
|
require "frecon/base"
|
11
13
|
|
12
14
|
require "frecon/database"
|
13
15
|
require "frecon/server"
|
14
16
|
require "frecon/console"
|
17
|
+
|
18
|
+
require "frecon/scrapers"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frecon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Craig
|
@@ -57,6 +57,20 @@ dependencies:
|
|
57
57
|
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
59
|
version: '4.0'
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: httparty
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.13'
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.13'
|
60
74
|
description: A JSON API for scouting FRC competitions that manages the database for
|
61
75
|
the user.
|
62
76
|
email: frc-frecon@googlegroups.com
|
@@ -68,6 +82,7 @@ files:
|
|
68
82
|
- bin/frecon
|
69
83
|
- lib/frecon.rb
|
70
84
|
- lib/frecon/base.rb
|
85
|
+
- lib/frecon/base/bson.rb
|
71
86
|
- lib/frecon/base/object.rb
|
72
87
|
- lib/frecon/base/variables.rb
|
73
88
|
- lib/frecon/console.rb
|
@@ -94,6 +109,8 @@ files:
|
|
94
109
|
- lib/frecon/position.rb
|
95
110
|
- lib/frecon/request_error.rb
|
96
111
|
- lib/frecon/routes.rb
|
112
|
+
- lib/frecon/scraper.rb
|
113
|
+
- lib/frecon/scrapers.rb
|
97
114
|
- lib/frecon/server.rb
|
98
115
|
homepage: https://github.com/frc-frecon/frecon
|
99
116
|
licenses:
|