wikidata_position_history 1.4.3 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35a434aeccb7428a5d7ebc4ff9b534e6477980d153e744760459c3125c4e90ae
4
- data.tar.gz: bf8f4773d018ae8800104989e2052689ea19217a2a2cafbc09c8d4e4839ce7d0
3
+ metadata.gz: 6a2bc5a49d34a368363b7e92ec9e1b0d08b141d96babd15eccf2913d99e9b7b0
4
+ data.tar.gz: 87594145f811917672fd4772722e086907d508479d73b43bfb21a0aac24e5d27
5
5
  SHA512:
6
- metadata.gz: 9900bcc56726b22bf6a2e590400298fdd50dec62c992c1613fd33d2250d4a909ceed1dfc409ec94d5c4ff992a4ffbfcd15893fd9522f3061e967ca2370b03fad
7
- data.tar.gz: c1d5ad9bdf3378afbebb3b97ffdd0bebca18e88be03605e0ba5d6a379efee73e5293b6881ebe854873fe879b1409320d721f20162d15a654350ccea4587e506c
6
+ metadata.gz: 6eb361e602c3a34c97bd8b584b4029135d9bb8e14c1f99b2ed513ce049f8df780c9b09ac31941c31a7ebea544d0a6cc0065cb2210bc4af4448de66cfb40800c0
7
+ data.tar.gz: 1b07fb333e1f13d25985420ec6700f2b0dc81dc98a5c4a762713bcf8426c532b48e28f6d80646d7c5ea85692f63e921748a603708e4d9e7286f254bc8c665e21
@@ -1,6 +1,86 @@
1
1
  # Changelog
2
2
 
3
- # [1.4.3] 2020-09-05
3
+ # [1.9.0] 2020-09-11
4
+
5
+ ## Enhancements
6
+
7
+ * If a position has any successor or predecessor offices (in "replaces"
8
+ (P1365) or "replaced by" (P1366)) the report will now display those.
9
+
10
+ # [1.8.0] 2020-09-09
11
+
12
+ ## Enhancements
13
+
14
+ * If the very latest person we know of having held this position also
15
+ has a 'replaced by' qualifier, that’s a sign that the successor should
16
+ really also have a suitable P39, and actually appear here too. So we
17
+ want to display a warning in such cases. Likewise if the earliest person
18
+ we know if also has a 'replaces'
19
+
20
+ * This report is meant to be used with positions that are held by only a
21
+ single person at a time. Using it to produce a report of everyone who
22
+ has been, say, a Member of the UK Parliament, is the sort of thing that
23
+ will cause all manner of havoc, as it will try to display tens of
24
+ thousands of people, all of whom have overlaps with other members etc.
25
+ So we now sanity-check first of all that the position isn't legislative,
26
+ and produce a nice "Don’t do that!" message in such cases.
27
+
28
+ * It seems that the recent ability to handle dates that are only know at
29
+ decade-level precision isn’t actually enough, as we have some that we
30
+ only know at century-level precision! (For example, that the position of
31
+ Lord Chancellor of Ireland was created some time in the 12th Century.)
32
+ Such dates will now appear in a nicer format.
33
+
34
+ * Sometimes updating the table looks like something has changed, but
35
+ really the only difference is that a few of people who have no dates
36
+ are shuffled around a bit in the list. This is because we previously
37
+ only sorted by date order, so people with no dates were effectively in a
38
+ random order. Now we sort those people by ID too, which should minimise
39
+ the number of times an update will appear in your watchlist, only to
40
+ discover nothing significant actually happened.
41
+
42
+ # [1.7.0] 2020-09-08
43
+
44
+ ## Enchancements
45
+
46
+ * Yesterday’s future, when we said we’d do something a little better
47
+ with positions that have multiple inception or abolition dates, has
48
+ arrived. Now we display all of them (with a warning), rather than just
49
+ picking one semi-randomly.
50
+
51
+ ## Improvements
52
+
53
+ * A query like https://w.wiki/bVz is taking about 6 seconds to run.
54
+ Changing that to https://w.wiki/bW3 drops that to about half a second.
55
+ If you were to guess that the first has now been replaced by the
56
+ second, you’d be entirely correct.
57
+
58
+ # [1.6.0] 2020-09-07
59
+
60
+ ## Enhancements
61
+
62
+ * If a position has an inception date and/or abolition date, those will
63
+ now also be displayed. (If a position has more than one of either of
64
+ those — which really shouldn’t happen, but sometimes does — then the
65
+ behaviour may not be particularly sensible. Later evolutions of this
66
+ feature will hopefully handle that better.)
67
+
68
+ ## Fixes
69
+
70
+ * Previously, any warnings would be displayed at the bottom of the page,
71
+ which was fine if this table was the only thing on the page, but would
72
+ be slightly odd if there was other discussion after it. Now the
73
+ footnotes are explicitly displayed immediately after the table.
74
+
75
+ # [1.5.0] 2020-09-06
76
+
77
+ ## Enhancements
78
+
79
+ * When showing the results for a position from long long ago (such as
80
+ the High Kings of Ireland), display the dates as "862 – 879" not as
81
+ "0862 – 0879"
82
+ * If we only know that someone took (or left) office sometime in a given
83
+ decade (i.e. at date precision 8), display that as (say) "1930s"
4
84
 
5
85
  ## Fixes
6
86
 
@@ -54,6 +54,8 @@ module QueryService
54
54
  class WikidataDate
55
55
  include Comparable
56
56
 
57
+ DATELEN = { '11' => 10, '10' => 7, '9' => 4, '8' => 4, '7' => 2 }.freeze
58
+
57
59
  def initialize(str, precision)
58
60
  @str = str
59
61
  @raw_precision = precision.to_s
@@ -66,12 +68,7 @@ module QueryService
66
68
  end
67
69
 
68
70
  def to_s
69
- return str if precision == '11'
70
- return str[0..6] if precision == '10'
71
- return str[0..3] if precision == '9'
72
-
73
- warn "Cannot handle precision #{precision} for #{str}"
74
- str
71
+ precisioned_string.delete_prefix('0')
75
72
  end
76
73
 
77
74
  def empty?
@@ -99,5 +96,19 @@ module QueryService
99
96
  def parts
100
97
  to_s.split('-')
101
98
  end
99
+
100
+ def truncated_string
101
+ return str[0...DATELEN[precision]] if DATELEN.key?(precision)
102
+
103
+ warn "Cannot handle precision #{precision} for #{str}"
104
+ str
105
+ end
106
+
107
+ def precisioned_string
108
+ return "#{truncated_string}. century" if precision == '7'
109
+ return "#{truncated_string}s" if precision == '8'
110
+
111
+ truncated_string
112
+ end
102
113
  end
103
114
  end
@@ -7,7 +7,7 @@ module WikidataPositionHistory
7
7
  # This is distinct from the mandate query itself to avoid complex
8
8
  # GROUP BY scenarios where people have multiple values for
9
9
  # biographical properties.
10
- class BioData < ItemQuery
10
+ class BioQuery < ItemQuery
11
11
  def raw_sparql
12
12
  <<~SPARQL
13
13
  # holder-biodata
@@ -24,7 +24,7 @@ module WikidataPositionHistory
24
24
  end
25
25
 
26
26
  # Represents a single row returned from the Position query
27
- class BioData
27
+ class BioRow
28
28
  def initialize(row)
29
29
  @row = row
30
30
  end
@@ -23,7 +23,11 @@ module WikidataPositionHistory
23
23
  attr_reader :itemid
24
24
 
25
25
  def sparql
26
- raw_sparql % itemid
26
+ raw_sparql % sparql_args
27
+ end
28
+
29
+ def sparql_args
30
+ itemid
27
31
  end
28
32
 
29
33
  def json
@@ -3,7 +3,7 @@
3
3
  module WikidataPositionHistory
4
4
  module SPARQL
5
5
  # SPARQL for fetching all officeholdings of a position
6
- class Mandates < ItemQuery
6
+ class MandatesQuery < ItemQuery
7
7
  def raw_sparql
8
8
  <<~SPARQL
9
9
  # position-mandates
@@ -21,14 +21,14 @@ module WikidataPositionHistory
21
21
  OPTIONAL { ?posn pq:P1545 ?ordinal }
22
22
  OPTIONAL { ?posn pq:P5102 ?nature }
23
23
  }
24
- ORDER BY DESC(?start_date)
24
+ ORDER BY DESC(?start_date) ?item
25
25
  SPARQL
26
26
  end
27
27
  end
28
28
  end
29
29
 
30
30
  # Represents a single row returned from the Mandates query
31
- class Mandate
31
+ class MandateRow
32
32
  def initialize(row)
33
33
  @row = row
34
34
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WikidataPositionHistory
4
+ module SPARQL
5
+ # SPARQL for fetching metadata about a position
6
+ class PositionQuery < ItemQuery
7
+ def raw_sparql
8
+ <<~SPARQL
9
+ # position-metadata
10
+
11
+ SELECT DISTINCT ?item ?inception ?inception_precision ?abolition ?abolition_precision
12
+ ?replaces ?replacedBy
13
+ ?isPosition ?isLegislator
14
+ WHERE {
15
+ VALUES ?item { wd:%s }
16
+ BIND(EXISTS { wd:%s wdt:P279+ wd:Q4164871 } as ?isPosition)
17
+ BIND(EXISTS { wd:%s wdt:P279+ wd:Q4175034 } as ?isLegislator)
18
+ OPTIONAL { ?item p:P571 [ a wikibase:BestRank ;
19
+ psv:P571 [ wikibase:timeValue ?inception; wikibase:timePrecision ?inception_precision ]
20
+ ] }
21
+ OPTIONAL { ?item p:P576 [ a wikibase:BestRank ;
22
+ psv:P576 [ wikibase:timeValue ?abolition; wikibase:timePrecision ?abolition_precision ]
23
+ ] }
24
+ OPTIONAL { ?item wdt:P1365 ?replaces }
25
+ OPTIONAL { ?item wdt:P1366 ?replacedBy }
26
+ }
27
+ SPARQL
28
+ end
29
+
30
+ def sparql_args
31
+ [itemid] * 3
32
+ end
33
+ end
34
+ end
35
+
36
+ # Represents a single row returned from the Position query
37
+ class PositionRow
38
+ def initialize(row)
39
+ @row = row
40
+ end
41
+
42
+ def item
43
+ QueryService::WikidataItem.new(row.dig(:item, :value))
44
+ end
45
+
46
+ def inception_date
47
+ return if inception_date_raw.empty?
48
+
49
+ QueryService::WikidataDate.new(inception_date_raw, inception_date_precision)
50
+ end
51
+
52
+ def abolition_date
53
+ return if abolition_date_raw.empty?
54
+
55
+ QueryService::WikidataDate.new(abolition_date_raw, abolition_date_precision)
56
+ end
57
+
58
+ def replaces
59
+ return if replaces_raw.to_s.empty?
60
+
61
+ QueryService::WikidataItem.new(replaces_raw)
62
+ end
63
+
64
+ def replaced_by
65
+ return if replaced_by_raw.to_s.empty?
66
+
67
+ QueryService::WikidataItem.new(replaced_by_raw)
68
+ end
69
+
70
+ def position?
71
+ row.dig(:isPosition, :value) == 'true'
72
+ end
73
+
74
+ def legislator?
75
+ row.dig(:isLegislator, :value) == 'true'
76
+ end
77
+
78
+ private
79
+
80
+ attr_reader :row
81
+
82
+ def replaces_raw
83
+ row.dig(:replaces, :value)
84
+ end
85
+
86
+ def replaced_by_raw
87
+ row.dig(:replacedBy, :value)
88
+ end
89
+
90
+ def inception_date_raw
91
+ row.dig(:inception, :value).to_s[0..9]
92
+ end
93
+
94
+ def abolition_date_raw
95
+ row.dig(:abolition, :value).to_s[0..9]
96
+ end
97
+
98
+ def inception_date_precision
99
+ row.dig(:inception_precision, :value)
100
+ end
101
+
102
+ def abolition_date_precision
103
+ row.dig(:abolition_precision, :value)
104
+ end
105
+ end
106
+ end
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'query_service'
4
4
  require 'sparql/item_query'
5
- require 'sparql/position_data'
6
- require 'sparql/bio_data'
7
- require 'sparql/mandates'
5
+ require 'sparql/position_query'
6
+ require 'sparql/bio_query'
7
+ require 'sparql/mandates_query'
8
8
  require 'wikidata_position_history/checks'
9
9
  require 'wikidata_position_history/template'
10
10
  require 'wikidata_position_history/report'
@@ -25,11 +25,11 @@ module WikidataPositionHistory
25
25
  current.prev
26
26
  end
27
27
 
28
- def latest_holder?
28
+ def later_holder?
29
29
  !!later
30
30
  end
31
31
 
32
- def earliest_holder?
32
+ def earlier_holder?
33
33
  !!earlier
34
34
  end
35
35
  end
@@ -92,7 +92,7 @@ module WikidataPositionHistory
92
92
  # Does the 'replaces' match the previous item in the list?
93
93
  class WrongPredecessor < Check
94
94
  def problem?
95
- earliest_holder? && !!predecessor && (earlier.item != predecessor)
95
+ earlier_holder? && !!predecessor && (earlier.item != predecessor)
96
96
  end
97
97
 
98
98
  def headline
@@ -104,10 +104,25 @@ module WikidataPositionHistory
104
104
  end
105
105
  end
106
106
 
107
+ # Is there a 'replaces' but no previous item in the list?
108
+ class MissingPredecessor < Check
109
+ def problem?
110
+ predecessor && !earlier_holder?
111
+ end
112
+
113
+ def headline
114
+ 'Inconsistent predecessor'
115
+ end
116
+
117
+ def possible_explanation
118
+ "#{current.item} has a {{P|1365}} of #{predecessor}, but does not follow anyone here"
119
+ end
120
+ end
121
+
107
122
  # Does the 'replaced by' match the next item in the list?
108
123
  class WrongSuccessor < Check
109
124
  def problem?
110
- latest_holder? && !!successor && (later.item != successor)
125
+ later_holder? && !!successor && (later.item != successor)
111
126
  end
112
127
 
113
128
  def headline
@@ -119,6 +134,21 @@ module WikidataPositionHistory
119
134
  end
120
135
  end
121
136
 
137
+ # Is there a 'replaced by' but no next item in the list?
138
+ class MissingSuccessor < Check
139
+ def problem?
140
+ successor && !later_holder?
141
+ end
142
+
143
+ def headline
144
+ 'Inconsistent successor'
145
+ end
146
+
147
+ def possible_explanation
148
+ "#{current.item} has a {{P|1366}} of #{successor}, but is not followed by anyone here"
149
+ end
150
+ end
151
+
122
152
  # Does the end date overlap with the successor's start date?
123
153
  class Overlap < Check
124
154
  def problem?
@@ -3,7 +3,9 @@
3
3
  module WikidataPositionHistory
4
4
  # Date for a single mandate row, to be passed to the report template
5
5
  class MandateData
6
- CHECKS = [Check::MissingFields, Check::WrongPredecessor, Check::WrongSuccessor, Check::Overlap].freeze
6
+ CHECKS = [Check::MissingFields, Check::Overlap,
7
+ Check::WrongPredecessor, Check::MissingPredecessor,
8
+ Check::WrongSuccessor, Check::MissingSuccessor].freeze
7
9
 
8
10
  def initialize(later, current, earlier)
9
11
  @later = later
@@ -40,6 +42,93 @@ module WikidataPositionHistory
40
42
  attr_reader :later, :current, :earlier
41
43
  end
42
44
 
45
+ # Data about the position itself, to be passed to the report template
46
+ class Metadata
47
+ # simplified version of a WikidataPositionHistory::Check
48
+ Warning = Struct.new(:headline, :explanation)
49
+
50
+ def initialize(rows)
51
+ @rows = rows
52
+ end
53
+
54
+ def item
55
+ rows.map(&:item).first
56
+ end
57
+
58
+ def replaces
59
+ return if replaces_list.empty?
60
+
61
+ replaces_list.map(&:qlink).join(', ')
62
+ end
63
+
64
+ def replaced_by
65
+ return if replaced_by_list.empty?
66
+
67
+ replaced_by_list.map(&:qlink).join(', ')
68
+ end
69
+
70
+ def inception_date
71
+ return if inception_dates.empty?
72
+
73
+ inception_dates.join(' / ')
74
+ end
75
+
76
+ def inception_warning
77
+ count = inception_dates.count
78
+
79
+ return if count == 1
80
+ return Warning.new('Missing field', "#{item_qlink} is missing {{P|571}}") if count.zero?
81
+
82
+ Warning.new('Multiple values', "#{item_qlink} has more than one {{P|571}}")
83
+ end
84
+
85
+ def abolition_date
86
+ return if abolition_dates.empty?
87
+
88
+ abolition_dates.join(' / ')
89
+ end
90
+
91
+ def abolition_warning
92
+ return unless abolition_dates.count > 1
93
+
94
+ Warning.new('Multiple values', "#{item_qlink} has more than one {{P|576}}")
95
+ end
96
+
97
+ def position?
98
+ # this should be the same everywhere
99
+ rows.map(&:position?).first
100
+ end
101
+
102
+ def legislator?
103
+ # this should be the same everywhere
104
+ rows.map(&:legislator?).first
105
+ end
106
+
107
+ private
108
+
109
+ attr_reader :rows
110
+
111
+ def replaces_list
112
+ rows.map(&:replaces).compact.uniq(&:id).sort_by(&:id)
113
+ end
114
+
115
+ def replaced_by_list
116
+ rows.map(&:replaced_by).compact.uniq(&:id).sort_by(&:id)
117
+ end
118
+
119
+ def inception_dates
120
+ rows.map(&:inception_date).compact.uniq(&:to_s).sort
121
+ end
122
+
123
+ def abolition_dates
124
+ rows.map(&:abolition_date).compact.uniq(&:to_s).sort
125
+ end
126
+
127
+ def item_qlink
128
+ item.qlink
129
+ end
130
+ end
131
+
43
132
  # The entire wikitext generated for this report
44
133
  class Report
45
134
  def initialize(position_id, template_class = ReportTemplate)
@@ -50,9 +139,10 @@ module WikidataPositionHistory
50
139
  attr_reader :position_id, :template_class
51
140
 
52
141
  def wikitext
142
+ return legislator_template if metadata.legislator?
53
143
  return no_items_output if mandates.empty?
54
144
 
55
- output
145
+ template_class.new(template_params).output
56
146
  end
57
147
 
58
148
  def header
@@ -70,16 +160,22 @@ module WikidataPositionHistory
70
160
  [header, wikitext].join("\n")
71
161
  end
72
162
 
163
+ def template_params
164
+ {
165
+ metadata: metadata,
166
+ table_rows: table_rows,
167
+ sparql_url: sparql.wdqs_url,
168
+ }
169
+ end
170
+
73
171
  private
74
172
 
75
173
  def metadata
76
- # TODO: we might get more than one response, if a position has
77
- # multiple dates
78
- @metadata ||= SPARQL::PositionData.new(position_id).results_as(PositionData).first
174
+ @metadata ||= Metadata.new(SPARQL::PositionQuery.new(position_id).results_as(PositionRow))
79
175
  end
80
176
 
81
177
  def biodata
82
- @biodata ||= SPARQL::BioData.new(position_id).results_as(BioData)
178
+ @biodata ||= SPARQL::BioQuery.new(position_id).results_as(BioRow)
83
179
  end
84
180
 
85
181
  def biodata_for(officeholder)
@@ -91,26 +187,19 @@ module WikidataPositionHistory
91
187
  end
92
188
 
93
189
  def sparql
94
- @sparql ||= SPARQL::Mandates.new(position_id)
190
+ @sparql ||= SPARQL::MandatesQuery.new(position_id)
95
191
  end
96
192
 
97
193
  def mandates
98
- @mandates ||= sparql.results_as(Mandate)
194
+ @mandates ||= sparql.results_as(MandateRow)
99
195
  end
100
196
 
101
197
  def no_items_output
102
198
  "\n{{PositionHolderHistory/error_no_holders|id=#{position_id}}}\n"
103
199
  end
104
200
 
105
- def output
106
- template_class.new(template_params).output
107
- end
108
-
109
- def template_params
110
- {
111
- table_rows: table_rows,
112
- sparql_url: sparql.wdqs_url,
113
- }
201
+ def legislator_template
202
+ "\n{{PositionHolderHistory/error_legislator|id=#{position_id}}}\n"
114
203
  end
115
204
 
116
205
  def table_rows
@@ -16,22 +16,68 @@ module WikidataPositionHistory
16
16
  attr_reader :data
17
17
 
18
18
  def template
19
- @template ||= ERB.new(template_text)
19
+ @template ||= ERB.new(template_text, nil, '-')
20
20
  end
21
21
 
22
22
  def template_text
23
23
  <<~ERB
24
24
  {| class="wikitable" style="text-align: center; border: none;"
25
- <% table_rows.map(&:values).each do |mandate, bio| %>|-
25
+ <% if metadata.abolition_date -%>
26
+ |-
27
+ | colspan="2" style="border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Position abolished''':
28
+ | style="border: none; background: #fff; text-align: left;" | <%= metadata.abolition_date %>
29
+ | style="border: none; background: #fff; text-align: left;" | \
30
+ <% [metadata.abolition_warning].compact.each do |warning| -%>
31
+ <span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]]&nbsp;<span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span>&nbsp;<ref><%= warning.explanation %></ref></span>\
32
+ <% end %>
33
+ <% end -%>
34
+ <% if metadata.replaced_by -%>
35
+ |-
36
+ | colspan="2" style="border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Replaced by''':
37
+ | style=" border: none; background: #fff; text-align: left;" | <%= metadata.replaced_by %>
38
+ | style=" border: none; background: #fff; text-align: left;" |
39
+ <% end -%>
40
+ <% if metadata.replaced_by || metadata.abolition_date -%>
41
+ |-
42
+ | colspan="3" style="padding:0.5em; border: none; background: #fff"> |&nbsp;
43
+ | colspan="1" style="padding:0.5em; border: none; background: #fff"> |&nbsp;
44
+ <% end -%>
45
+ <% table_rows.map(&:values).each do |mandate, bio| -%>
46
+ |-
26
47
  | style="padding:0.5em 2em" | <%= mandate.ordinal_string %>
27
48
  | style="padding:0.5em 2em" | <%= bio.map(&:image_link).first %>
28
49
  | style="padding:0.5em 2em" | <span style="font-size: <%= mandate.acting? ? '1.25em; font-style: italic;' : '1.5em' %>; display: block;"><%= mandate.person %></span> <%= mandate.dates %>
29
- | style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" | <% mandate.warnings.each do |warning| %><span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]]&nbsp;<span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span>&nbsp;<ref><%= warning.explanation %></ref></span><% end %>
30
- <% end %>|}
50
+ | style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" | \
51
+ <% mandate.warnings.each do |warning| -%>
52
+ <span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]]&nbsp;<span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span>&nbsp;<ref><%= warning.explanation %></ref></span>\
53
+ <% end %>
54
+ <% end -%>
55
+ <% if metadata.replaced_by || metadata.abolition_date -%>
56
+ |-
57
+ | colspan="3" style="padding:0.5em; border: none; background: #fff"> |&nbsp;
58
+ | colspan="1" style="padding:0.5em; border: none; background: #fff"> |&nbsp;
59
+ <% end -%>
60
+ <% if metadata.inception_date -%>
61
+ |-
62
+ | colspan="2" style="border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Position created''':
63
+ | style="border: none; background: #fff; text-align: left;" | <%= metadata.inception_date %>
64
+ | style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" | \
65
+ <% [metadata.inception_warning].compact.each do |warning| -%>
66
+ <span style="display: block">[[File:Pictogram voting comment.svg|15px|link=]]&nbsp;<span style="color: #d33; font-weight: bold; vertical-align: middle;"><%= warning.headline %></span>&nbsp;<ref><%= warning.explanation %></ref></span>\
67
+ <% end %>
68
+ <% end -%>
69
+ <% if metadata.replaces -%>
70
+ |-
71
+ | colspan="2" style=" border: none; background: #fff; font-size: 1.15em; text-align: right;" | '''Replaces''':
72
+ | style="border: none; background: #fff; text-align: left;" | <%= metadata.replaces %>
73
+ | style="padding:0.5em 2em 0.5em 1em; border: none; background: #fff; text-align: left;" |
74
+ <% end -%>
75
+ |}
31
76
 
32
77
  <div style="margin-bottom:5px; border-bottom:3px solid #2f74d0; font-size:8pt">
33
78
  <div style="float:right">[<%= sparql_url %> WDQS]</div>
34
79
  </div>
80
+ {{reflist}}
35
81
  ERB
36
82
  end
37
83
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WikidataPositionHistory
4
- VERSION = '1.4.3'
4
+ VERSION = '1.9.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wikidata_position_history
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Bowden
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-09-05 00:00:00.000000000 Z
12
+ date: 2020-09-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mediawiki-replaceable-content
@@ -204,10 +204,10 @@ files:
204
204
  - exe/position-history-for-item
205
205
  - exe/update_wikidata_page
206
206
  - lib/query_service.rb
207
- - lib/sparql/bio_data.rb
207
+ - lib/sparql/bio_query.rb
208
208
  - lib/sparql/item_query.rb
209
- - lib/sparql/mandates.rb
210
- - lib/sparql/position_data.rb
209
+ - lib/sparql/mandates_query.rb
210
+ - lib/sparql/position_query.rb
211
211
  - lib/wikidata_position_history.rb
212
212
  - lib/wikidata_position_history/checks.rb
213
213
  - lib/wikidata_position_history/report.rb
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WikidataPositionHistory
4
- module SPARQL
5
- # SPARQL for fetching metadata about a position
6
- class PositionData < ItemQuery
7
- def raw_sparql
8
- <<~SPARQL
9
- # position-metadata
10
-
11
- SELECT DISTINCT ?inception ?inception_precision ?abolition ?abolition_precision ?isPosition
12
- WHERE {
13
- VALUES ?item { wd:%s }
14
- BIND(EXISTS { ?item wdt:P279+ wd:Q4164871 } as ?isPosition)
15
- OPTIONAL { ?item p:P571/psv:P571 [ wikibase:timeValue ?inception; wikibase:timePrecision ?inception_precision ] }
16
- OPTIONAL { ?item p:P576/psv:P576 [ wikibase:timeValue ?abolition; wikibase:timePrecision ?abolition_precision ] }
17
- SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
18
- }
19
- SPARQL
20
- end
21
- end
22
- end
23
-
24
- # Represents a single row returned from the Position query
25
- class PositionData
26
- def initialize(row)
27
- @row = row
28
- end
29
-
30
- def inception_date
31
- QueryService::WikidataDate.new(inception_date_raw, inception_date_precision)
32
- end
33
-
34
- def abolition_date
35
- QueryService::WikidataDate.new(abolition_date_raw, abolition_date_precision)
36
- end
37
-
38
- def position?
39
- row.dig(:isPosition, :value) == 'true'
40
- end
41
-
42
- private
43
-
44
- attr_reader :row
45
-
46
- def inception_date_raw
47
- row.dig(:inception, :value).to_s[0..9]
48
- end
49
-
50
- def abolition_date_raw
51
- row.dig(:abolition, :value).to_s[0..9]
52
- end
53
-
54
- def inception_date_precision
55
- row.dig(:inception_precision, :value)
56
- end
57
-
58
- def abolition_date_precision
59
- row.dig(:abolition_precision, :value)
60
- end
61
- end
62
- end