-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sources.rb
123 lines (95 loc) · 3.43 KB
/
Sources.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
class Sources
@sourceHash = {}
# a hash keyed on the source title since that's the unique ID as implied by the prob statement
# this makes ordering trickier, but the hash lookup for checking if we have a source
# is worth it instead of searching the entire list of sources.
# {
# "source title" => {
# "order" => 2,
# "object" => Source.new(...)
# },
# ...
# }
attr_accessor :sourceHash
def initialize(sources = [])
@sourceHash = {}
sources.each do |source|
if !source.is_a? Source
source = Source.new(source['title'], source['feed_url'], source['updated'], source['order']);
end
@sourceHash[source.title] = source
end
end
# returns the version of the passed-in source in the current source list, if any
def get(source)
return @sourceHash[source.title]
end
# returns the sorted list. nlogn expensive.
def getOrdered
sorted = @sourceHash.values.sort_by do |source|
# when updating a source, it's possible that we have identital "order" values.
# e.g. we think the order is a,b,c, and the user updates that c goes into pos 1.
# it's not explicitly clear that the "right" answer is c,a,b or a,c,b, so we
# infer that the "lastest" update to pos 1 wins.
[ source.order, -source.updated ]
end
return sorted
end
# returns the version of the passed-in title in the current source list, if any
def getByTitle(title)
return @sourceHash[title]
end
# adds a source to the list, or overwrites it if it's already there
def update(source)
@sourceHash[source.title] = source
end
# abstracts out the logic of whether a source should be updated in this list
def shouldUpdate(source)
if (!self.get(source) || source.newerThan(@sourceHash[source.title]))
self.update(source)
end
end
# takes a user source list and merges with the internal source hash.
# returns the new, merged list
def merge(userSourceList)
if $VERBOSE then puts "###### merging user source list with internal" end
userSourceList.each do |userSource|
userSource = Source.new(userSource['title'], userSource['feed_url'], userSource['updated'], userSource['order']);
if self.shouldUpdate(userSource)
if $VERBOSE then puts " updating source #{userSource.title}" end
self.update(userSource)
end
end
return @sourceHash
end
# returns a boolean whether self is the same as another Sources object
def sameAs(otherSources)
# early exit if possible
if (self.sourceHash.length != otherSources.sourceHash.length)
if $VERBOSE then puts "diferent lengths" end
return false
end
# order them first to make sure the ordering logic is identical
mineOrdered = self.getOrdered
theirsOrdered = otherSources.getOrdered
# check each one, in order, for equality
for i in 0...[mineOrdered.length, theirsOrdered.length].max do
mine = mineOrdered[i]
theirs = theirsOrdered[i]
# if missing in one of them
if !mine
if $VERBOSE then puts "missing the source for #{theirs.title} in my list" end
return false
elsif !theirs
if $VERBOSE then puts "missing the source for #{mine.title} in their list" end
return false
elsif !mine.equals?(theirs)
if $VERBOSE then puts "##{i} is different" end
pp mine
pp theirs
return false
end
end
return true
end
end