Merge lp:~vthompson/ubuntu-weather-app/reboot-sunrise-sunset into lp:ubuntu-weather-app
- reboot-sunrise-sunset
- Merge into reboot
Status: | Merged |
---|---|
Approved by: | Andrew Hayzen |
Approved revision: | 64 |
Merged at revision: | 65 |
Proposed branch: | lp:~vthompson/ubuntu-weather-app/reboot-sunrise-sunset |
Merge into: | lp:ubuntu-weather-app |
Diff against target: |
469 lines (+348/-8) 7 files modified
app/components/DayDelegate.qml (+2/-2) app/components/ForecastDetailsDelegate.qml (+1/-0) app/data/WeatherApi.js (+6/-0) app/data/suncalc.js (+300/-0) app/ui/HomePage.qml (+9/-4) app/ui/LocationPane.qml (+5/-2) debian/copyright (+25/-0) |
To merge this branch: | bzr merge lp:~vthompson/ubuntu-weather-app/reboot-sunrise-sunset |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Hayzen | Approve | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Review via email: mp+263171@code.launchpad.net |
Commit message
Use sunrise/sunset from API if available, otherwise use calculated times
Description of the change
Use sunrise/sunset from API if available, otherwise use calculated times
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
- 58. By Victor Thompson
-
get each date in forecast
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:58
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 59. By Victor Thompson
-
Fix spelling mistake: mooon
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:59
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Andrew Hayzen (ahayzen) wrote : | # |
Some inline code comments/questions to start off with :-)
- 60. By Victor Thompson
-
Update date getter and formatting functions
Victor Thompson (vthompson) wrote : | # |
Added responses and updated mp.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:60
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Nekhelesh Ramananthan (nik90) wrote : | # |
> return Qt.formatDate(
We should *never* be exposing the format as a translatable string and should instead be using Qt.locale to display the time/date as per the locale format. Considering that this is something that is also present in trunk, it doesn't block this MP.
- 61. By Victor Thompson
-
Update copyright file
- 62. By Victor Thompson
-
Add dots
- 63. By Victor Thompson
-
One more try
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:63
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 64. By Victor Thompson
-
Change to BSD 2-clause
Andrew Hayzen (ahayzen) wrote : | # |
Thanks for the extra changes, LGTM :-)
Preview Diff
1 | === modified file 'app/components/DayDelegate.qml' |
2 | --- app/components/DayDelegate.qml 2015-06-21 14:02:58 +0000 |
3 | +++ app/components/DayDelegate.qml 2015-07-25 21:36:51 +0000 |
4 | @@ -224,13 +224,13 @@ |
5 | ForecastDetailsDelegate { |
6 | id: sunriseForecast |
7 | forecast: i18n.tr("Sunrise") |
8 | - // FIXME: need icon |
9 | + imageName: "info" |
10 | } |
11 | |
12 | ForecastDetailsDelegate { |
13 | id: sunsetForecast |
14 | forecast: i18n.tr("Sunset") |
15 | - // FIXME: need icon |
16 | + imageName: "info" |
17 | } |
18 | } |
19 | } |
20 | |
21 | === modified file 'app/components/ForecastDetailsDelegate.qml' |
22 | --- app/components/ForecastDetailsDelegate.qml 2015-06-21 15:02:05 +0000 |
23 | +++ app/components/ForecastDetailsDelegate.qml 2015-07-25 21:36:51 +0000 |
24 | @@ -24,6 +24,7 @@ |
25 | spacing: units.gu(2) |
26 | visible: value !== "" |
27 | |
28 | + property alias imageName: icon.name |
29 | property alias imageSource: icon.source |
30 | property alias forecast: forecastLabel.text |
31 | property alias value: forecastValue.text |
32 | |
33 | === modified file 'app/data/WeatherApi.js' |
34 | --- app/data/WeatherApi.js 2015-04-27 00:57:35 +0000 |
35 | +++ app/data/WeatherApi.js 2015-07-25 21:36:51 +0000 |
36 | @@ -512,6 +512,7 @@ |
37 | "daily": combinedData[0]["DailyForecasts"], |
38 | "forecast": combinedData[0]["HourlyForecasts"], |
39 | "current": combinedData[0]["StandardObservation"], |
40 | + "sunRiseSet": combinedData[0]["SunRiseSet"], |
41 | }; |
42 | print("["+location.name+"] "+JSON.stringify(localNow)); |
43 | // add openweathermap id for faster responses |
44 | @@ -522,6 +523,7 @@ |
45 | for(var x=0;x<5;x++) { |
46 | var dayData = data["daily"][x], |
47 | date = getLocationTime(((dayData.validDate*1000)-1000)+offset); // minus 1 sec to handle +/-12 TZ |
48 | + var sunRiseSet = data["sunRiseSet"][x]; |
49 | day = date.year+"-"+date.month+"-"+date.date; |
50 | if(!todayDate) { |
51 | if(localNow.year+"-"+localNow.month+"-"+localNow.date > day) { |
52 | @@ -531,6 +533,10 @@ |
53 | todayDate = date; |
54 | } |
55 | tmpResult[day] = _buildDayFormat(date, dayData, nowMs); |
56 | + var sunrise = new Date(sunRiseSet.rise*1000); |
57 | + var sunset = new Date(sunRiseSet.set*1000); |
58 | + tmpResult[day].sunrise = sunrise.toLocaleTimeString(); |
59 | + tmpResult[day].sunset = sunset.toLocaleTimeString(); |
60 | } |
61 | // |
62 | if(data["forecast"] !== undefined) { |
63 | |
64 | === added file 'app/data/suncalc.js' |
65 | --- app/data/suncalc.js 1970-01-01 00:00:00 +0000 |
66 | +++ app/data/suncalc.js 2015-07-25 21:36:51 +0000 |
67 | @@ -0,0 +1,300 @@ |
68 | +/* |
69 | + (c) 2011-2015, Vladimir Agafonkin |
70 | + SunCalc is a JavaScript library for calculating sun/moon position and light phases. |
71 | + https://github.com/mourner/suncalc |
72 | +*/ |
73 | + |
74 | +// shortcuts for easier to read formulas |
75 | + |
76 | +var PI = Math.PI, |
77 | + sin = Math.sin, |
78 | + cos = Math.cos, |
79 | + tan = Math.tan, |
80 | + asin = Math.asin, |
81 | + atan = Math.atan2, |
82 | + acos = Math.acos, |
83 | + rad = PI / 180; |
84 | + |
85 | +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas |
86 | + |
87 | + |
88 | +// date/time constants and conversions |
89 | + |
90 | +var dayMs = 1000 * 60 * 60 * 24, |
91 | + J1970 = 2440588, |
92 | + J2000 = 2451545; |
93 | + |
94 | +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } |
95 | +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } |
96 | +function toDays(date) { return toJulian(date) - J2000; } |
97 | + |
98 | + |
99 | +// general calculations for position |
100 | + |
101 | +var e = rad * 23.4397; // obliquity of the Earth |
102 | + |
103 | +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } |
104 | +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } |
105 | + |
106 | +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } |
107 | +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } |
108 | + |
109 | +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } |
110 | + |
111 | + |
112 | +// general sun calculations |
113 | + |
114 | +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } |
115 | + |
116 | +function eclipticLongitude(M) { |
117 | + |
118 | + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center |
119 | + P = rad * 102.9372; // perihelion of the Earth |
120 | + |
121 | + return M + C + P + PI; |
122 | +} |
123 | + |
124 | +function sunCoords(d) { |
125 | + |
126 | + var M = solarMeanAnomaly(d), |
127 | + L = eclipticLongitude(M); |
128 | + |
129 | + return { |
130 | + dec: declination(L, 0), |
131 | + ra: rightAscension(L, 0) |
132 | + }; |
133 | +} |
134 | + |
135 | + |
136 | +var SunCalc = {}; |
137 | + |
138 | + |
139 | +// calculates sun position for a given date and latitude/longitude |
140 | + |
141 | +SunCalc.getPosition = function (date, lat, lng) { |
142 | + |
143 | + var lw = rad * -lng, |
144 | + phi = rad * lat, |
145 | + d = toDays(date), |
146 | + |
147 | + c = sunCoords(d), |
148 | + H = siderealTime(d, lw) - c.ra; |
149 | + |
150 | + return { |
151 | + azimuth: azimuth(H, phi, c.dec), |
152 | + altitude: altitude(H, phi, c.dec) |
153 | + }; |
154 | +}; |
155 | + |
156 | + |
157 | +// sun times configuration (angle, morning name, evening name) |
158 | + |
159 | +var times = SunCalc.times = [ |
160 | + [-0.833, 'sunrise', 'sunset' ], |
161 | + [ -0.3, 'sunriseEnd', 'sunsetStart' ], |
162 | + [ -6, 'dawn', 'dusk' ], |
163 | + [ -12, 'nauticalDawn', 'nauticalDusk'], |
164 | + [ -18, 'nightEnd', 'night' ], |
165 | + [ 6, 'goldenHourEnd', 'goldenHour' ] |
166 | +]; |
167 | + |
168 | +// adds a custom time to the times config |
169 | + |
170 | +SunCalc.addTime = function (angle, riseName, setName) { |
171 | + times.push([angle, riseName, setName]); |
172 | +}; |
173 | + |
174 | + |
175 | +// calculations for sun times |
176 | + |
177 | +var J0 = 0.0009; |
178 | + |
179 | +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } |
180 | + |
181 | +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } |
182 | +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } |
183 | + |
184 | +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } |
185 | + |
186 | +// returns set time for the given sun altitude |
187 | +function getSetJ(h, lw, phi, dec, n, M, L) { |
188 | + |
189 | + var w = hourAngle(h, phi, dec), |
190 | + a = approxTransit(w, lw, n); |
191 | + return solarTransitJ(a, M, L); |
192 | +} |
193 | + |
194 | + |
195 | +// calculates sun times for a given date and latitude/longitude |
196 | + |
197 | +SunCalc.getTimes = function (date, lat, lng) { |
198 | + |
199 | + var lw = rad * -lng, |
200 | + phi = rad * lat, |
201 | + |
202 | + d = toDays(date), |
203 | + n = julianCycle(d, lw), |
204 | + ds = approxTransit(0, lw, n), |
205 | + |
206 | + M = solarMeanAnomaly(ds), |
207 | + L = eclipticLongitude(M), |
208 | + dec = declination(L, 0), |
209 | + |
210 | + Jnoon = solarTransitJ(ds, M, L), |
211 | + |
212 | + i, len, time, Jset, Jrise; |
213 | + |
214 | + |
215 | + var result = { |
216 | + solarNoon: fromJulian(Jnoon), |
217 | + nadir: fromJulian(Jnoon - 0.5) |
218 | + }; |
219 | + |
220 | + for (i = 0, len = times.length; i < len; i += 1) { |
221 | + time = times[i]; |
222 | + |
223 | + Jset = getSetJ(time[0] * rad, lw, phi, dec, n, M, L); |
224 | + Jrise = Jnoon - (Jset - Jnoon); |
225 | + |
226 | + result[time[1]] = fromJulian(Jrise); |
227 | + result[time[2]] = fromJulian(Jset); |
228 | + } |
229 | + |
230 | + return result; |
231 | +}; |
232 | + |
233 | + |
234 | +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas |
235 | + |
236 | +function moonCoords(d) { // geocentric ecliptic coordinates of the moon |
237 | + |
238 | + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude |
239 | + M = rad * (134.963 + 13.064993 * d), // mean anomaly |
240 | + F = rad * (93.272 + 13.229350 * d), // mean distance |
241 | + |
242 | + l = L + rad * 6.289 * sin(M), // longitude |
243 | + b = rad * 5.128 * sin(F), // latitude |
244 | + dt = 385001 - 20905 * cos(M); // distance to the moon in km |
245 | + |
246 | + return { |
247 | + ra: rightAscension(l, b), |
248 | + dec: declination(l, b), |
249 | + dist: dt |
250 | + }; |
251 | +} |
252 | + |
253 | +SunCalc.getMoonPosition = function (date, lat, lng) { |
254 | + |
255 | + var lw = rad * -lng, |
256 | + phi = rad * lat, |
257 | + d = toDays(date), |
258 | + |
259 | + c = moonCoords(d), |
260 | + H = siderealTime(d, lw) - c.ra, |
261 | + h = altitude(H, phi, c.dec); |
262 | + |
263 | + // altitude correction for refraction |
264 | + h = h + rad * 0.017 / tan(h + rad * 10.26 / (h + rad * 5.10)); |
265 | + |
266 | + return { |
267 | + azimuth: azimuth(H, phi, c.dec), |
268 | + altitude: h, |
269 | + distance: c.dist |
270 | + }; |
271 | +}; |
272 | + |
273 | + |
274 | +// calculations for illumination parameters of the moon, |
275 | +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and |
276 | +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. |
277 | + |
278 | +SunCalc.getMoonIllumination = function (date) { |
279 | + |
280 | + var d = toDays(date), |
281 | + s = sunCoords(d), |
282 | + m = moonCoords(d), |
283 | + |
284 | + sdist = 149598000, // distance from Earth to Sun in km |
285 | + |
286 | + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), |
287 | + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), |
288 | + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - |
289 | + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); |
290 | + |
291 | + return { |
292 | + fraction: (1 + cos(inc)) / 2, |
293 | + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, |
294 | + angle: angle |
295 | + }; |
296 | +}; |
297 | + |
298 | + |
299 | +function hoursLater(date, h) { |
300 | + return new Date(date.valueOf() + h * dayMs / 24); |
301 | +} |
302 | + |
303 | +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article |
304 | + |
305 | +SunCalc.getMoonTimes = function (date, lat, lng) { |
306 | + var t = new Date(date); |
307 | + t.setHours(0); |
308 | + t.setMinutes(0); |
309 | + t.setSeconds(0); |
310 | + t.setMilliseconds(0); |
311 | + |
312 | + var hc = 0.133 * rad, |
313 | + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, |
314 | + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; |
315 | + |
316 | + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) |
317 | + for (var i = 1; i <= 24; i += 2) { |
318 | + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; |
319 | + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; |
320 | + |
321 | + a = (h0 + h2) / 2 - h1; |
322 | + b = (h2 - h0) / 2; |
323 | + xe = -b / (2 * a); |
324 | + ye = (a * xe + b) * xe + h1; |
325 | + d = b * b - 4 * a * h1; |
326 | + roots = 0; |
327 | + |
328 | + if (d >= 0) { |
329 | + dx = Math.sqrt(d) / (Math.abs(a) * 2); |
330 | + x1 = xe - dx; |
331 | + x2 = xe + dx; |
332 | + if (Math.abs(x1) <= 1) roots++; |
333 | + if (Math.abs(x2) <= 1) roots++; |
334 | + if (x1 < -1) x1 = x2; |
335 | + } |
336 | + |
337 | + if (roots === 1) { |
338 | + if (h0 < 0) rise = i + x1; |
339 | + else set = i + x1; |
340 | + |
341 | + } else if (roots === 2) { |
342 | + rise = i + (ye < 0 ? x2 : x1); |
343 | + set = i + (ye < 0 ? x1 : x2); |
344 | + } |
345 | + |
346 | + if (rise && set) break; |
347 | + |
348 | + h0 = h2; |
349 | + } |
350 | + |
351 | + var result = {}; |
352 | + |
353 | + if (rise) result.rise = hoursLater(t, rise); |
354 | + if (set) result.set = hoursLater(t, set); |
355 | + |
356 | + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; |
357 | + |
358 | + return result; |
359 | +}; |
360 | + |
361 | + |
362 | +// export as AMD module / Node module / browser variable |
363 | +//if (typeof define === 'function' && define.amd) define(SunCalc); |
364 | +//else if (typeof module !== 'undefined') module.exports = SunCalc; |
365 | +//else window.SunCalc = SunCalc; |
366 | + |
367 | +//}()); |
368 | |
369 | === modified file 'app/ui/HomePage.qml' |
370 | --- app/ui/HomePage.qml 2015-07-18 19:08:21 +0000 |
371 | +++ app/ui/HomePage.qml 2015-07-25 21:36:51 +0000 |
372 | @@ -66,16 +66,21 @@ |
373 | Format date object by given format. |
374 | */ |
375 | function formatTimestamp(dateData, format) { |
376 | - var date = new Date(dateData.year, dateData.month, dateData.date, dateData.hours, dateData.minutes) |
377 | - return Qt.formatDate(date, i18n.tr(format)) |
378 | + return Qt.formatDate(getDate(dateData), i18n.tr(format)) |
379 | } |
380 | |
381 | /* |
382 | Format time object by given format. |
383 | */ |
384 | function formatTime(dateData, format) { |
385 | - var date = new Date(dateData.year, dateData.month, dateData.date, dateData.hours, dateData.minutes) |
386 | - return Qt.formatTime(date, i18n.tr(format)) |
387 | + return Qt.formatTime(getDate(dateData), i18n.tr(format)) |
388 | + } |
389 | + |
390 | + /* |
391 | + Get Date object from dateData. |
392 | + */ |
393 | + function getDate(dateData) { |
394 | + return new Date(dateData.year, dateData.month, dateData.date, dateData.hours, dateData.minutes) |
395 | } |
396 | |
397 | /* |
398 | |
399 | === modified file 'app/ui/LocationPane.qml' |
400 | --- app/ui/LocationPane.qml 2015-06-21 14:02:58 +0000 |
401 | +++ app/ui/LocationPane.qml 2015-07-25 21:36:51 +0000 |
402 | @@ -20,6 +20,7 @@ |
403 | import Ubuntu.Components 1.2 |
404 | import Ubuntu.Components.ListItems 0.1 as ListItem |
405 | import "../components" |
406 | +import "../data/suncalc.js" as SunCalc |
407 | |
408 | Item { |
409 | id: locationItem |
410 | @@ -99,6 +100,8 @@ |
411 | image: (forecasts[x].icon !== undefined && iconMap[forecasts[x].icon] !== undefined) ? iconMap[forecasts[x].icon] : "", |
412 | chanceOfRain: forecasts[x].propPrecip === undefined ? -1 : forecasts[x].propPrecip, |
413 | humidity: emptyIfUndefined(forecasts[x].humidity, "%"), |
414 | + sunrise: forecasts[x].sunrise || SunCalc.SunCalc.getTimes(getDate(forecasts[x].date), data.location.coord.lat, data.location.coord.lon).sunrise.toLocaleTimeString(), |
415 | + sunset: forecasts[x].sunset || SunCalc.SunCalc.getTimes(getDate(forecasts[x].date), data.location.coord.lat, data.location.coord.lon).sunset.toLocaleTimeString(), |
416 | uvIndex: emptyIfUndefined(forecasts[x].uv), |
417 | wind: forecasts[x][tempUnits].windSpeed === undefined || forecasts[x].windDir === undefined |
418 | ? "" : Math.round(forecasts[x][tempUnits].windSpeed) + settings.windUnits + " " + forecasts[x].windDir |
419 | @@ -185,8 +188,8 @@ |
420 | humidity: model.humidity |
421 | // TODO: extra from API |
422 | //pollen: model.pollen |
423 | - //sunrise: model.sunrise |
424 | - //sunset: model.sunset |
425 | + sunrise: model.sunrise |
426 | + sunset: model.sunset |
427 | wind: model.wind |
428 | uvIndex: model.uvIndex |
429 | } |
430 | |
431 | === modified file 'debian/copyright' |
432 | --- debian/copyright 2015-02-02 15:25:53 +0000 |
433 | +++ debian/copyright 2015-07-25 21:36:51 +0000 |
434 | @@ -15,10 +15,35 @@ |
435 | 2015 Victor Thompson <victor.thompson@gmail.com> |
436 | License: GPL-3 |
437 | |
438 | +Files: app/data/suncalc.js |
439 | +Copyright: 2014 Vladimir Agafonkin |
440 | +License: BSD-2-clause |
441 | + |
442 | Files: debian/* |
443 | Copyright: 2013 Canonical Ltd. |
444 | License: LGPL-3 |
445 | |
446 | +License: BSD-2-clause |
447 | + Redistribution and use in source and binary forms, with or without modification, are |
448 | + permitted provided that the following conditions are met: |
449 | + . |
450 | + 1. Redistributions of source code must retain the above copyright notice, this list of |
451 | + conditions and the following disclaimer. |
452 | + . |
453 | + 2. Redistributions in binary form must reproduce the above copyright notice, this list |
454 | + of conditions and the following disclaimer in the documentation and/or other materials |
455 | + provided with the distribution. |
456 | + . |
457 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
458 | + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
459 | + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
460 | + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
461 | + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
462 | + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
463 | + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
464 | + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
465 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
466 | + |
467 | License: GPL-3 |
468 | This package is free software; you can redistribute it and/or |
469 | modify it under the terms of the GNU General Public |
PASSED: Continuous integration, rev:57 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- ci/122/ 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- utopic- amd64-ci/ 92 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- vivid-amd64- ci/122
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- weather- app-reboot- ci/122/ rebuild
http://