frecon 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|