comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java @ 2562:ba35dfb7c09a

FixingsOverview: Construct the Q sectors once. flys-artifacts/trunk@4088 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 20 Feb 2012 14:36:28 +0000
parents b3f6d49cdc80
children 59c920e73d8a
comparison
equal deleted inserted replaced
2561:b3f6d49cdc80 2562:ba35dfb7c09a
117 "SELECT" + 117 "SELECT" +
118 " MIN(position) AS start_km," + 118 " MIN(position) AS start_km," +
119 " MAX(position) AS stop_km " + 119 " MAX(position) AS stop_km " +
120 "FROM" + 120 "FROM" +
121 " wst_column_values " + 121 " wst_column_values " +
122 "WHERE " + 122 "WHERE" +
123 " wst_column_id = :column_id"; 123 " wst_column_id = :column_id";
124 124
125 public static class Range implements Serializable { 125 public static class Range implements Serializable {
126 126
127 protected double start; 127 protected double start;
133 public Range(double start, double end) { 133 public Range(double start, double end) {
134 this.start = start; 134 this.start = start;
135 this.end = end; 135 this.end = end;
136 } 136 }
137 137
138 public double getStart() {
139 return start;
140 }
141
142 public double getEnd() {
143 return end;
144 }
145
138 public boolean disjoint(Range other) { 146 public boolean disjoint(Range other) {
139 return start > other.end || other.start > end; 147 return start > other.end || other.start > end;
148 }
149
150 public boolean intersects(Range other) {
151 return !disjoint(other);
140 } 152 }
141 153
142 public boolean clip(Range other) { 154 public boolean clip(Range other) {
143 if (disjoint(other)) return false; 155 if (disjoint(other)) return false;
144 156
227 } 239 }
228 return sectors.size(); 240 return sectors.size();
229 } 241 }
230 } // class GaugeRange 242 } // class GaugeRange
231 243
244 public static class GaugeFinder {
245
246 protected List<GaugeRange> gauges;
247 protected boolean isKmUp;
248
249 public GaugeFinder(List<GaugeRange> gauges) {
250 this(gauges, true);
251 }
252
253 public GaugeFinder(
254 List<GaugeRange> gauges,
255 boolean isKmUp
256 ) {
257 this.gauges = gauges;
258 this.isKmUp = isKmUp;
259 }
260
261 public boolean getIsKmUp() {
262 return isKmUp;
263 }
264
265 public void setIsKmUp(boolean isKmUp) {
266 this.isKmUp = isKmUp;
267 }
268
269 public GaugeRange find(Range range) {
270 double km = isKmUp ? range.start : range.end;
271 for (GaugeRange gauge: gauges) {
272 if (gauge.inside(km)) {
273 return gauge;
274 }
275 }
276 return null;
277 }
278
279 public GaugeRange find(int gaugeId) {
280 for (GaugeRange gauge: gauges) {
281 if (gauge.gaugeId == gaugeId) {
282 return gauge;
283 }
284 }
285 return null;
286 }
287
288 public boolean loadDischargeSectors(Session session, int riverId) {
289
290 SQLQuery query = session.createSQLQuery(SQL_DISCHARGE_SECTORS)
291 .addScalar("gauge_id", StandardBasicTypes.INTEGER)
292 .addScalar("name", StandardBasicTypes.STRING)
293 .addScalar("value", StandardBasicTypes.DOUBLE);
294
295 query.setInteger("river_id", riverId);
296
297 List<Object []> list = query.list();
298
299 if (list.isEmpty()) {
300 log.warn("River " + riverId + " has no discharge sectors.");
301 return false;
302 }
303
304 GaugeRange gauge = null;
305
306 for (Object [] row: list) {
307 int gaugeId = (Integer)row[0];
308 String label = (String) row[1];
309 Double value = (Double) row[2];
310
311 if (gauge == null || gauge.gaugeId != gaugeId) {
312 if ((gauge = find(gaugeId)) == null) {
313 log.warn("Cannot find gauge for id " + gaugeId + ".");
314 continue;
315 }
316 }
317
318 gauge.addMainValue(label, value);
319 }
320
321 for (GaugeRange g: gauges) {
322 g.buildClasses();
323 }
324
325 return true;
326 }
327 } // class GaugeFinder
328
232 public static class QRange extends Range { 329 public static class QRange extends Range {
233 330
234 protected double q; 331 protected double q;
235 332
236 public QRange() { 333 public QRange() {
247 protected int sector; 344 protected int sector;
248 345
249 public SectorRange() { 346 public SectorRange() {
250 } 347 }
251 348
349 public SectorRange(SectorRange other) {
350 start = other.start;
351 end = other.end;
352 sector = other.sector;
353 }
354
252 public SectorRange(double start, double end, int sector) { 355 public SectorRange(double start, double end, int sector) {
253 super(start, end); 356 super(start, end);
254 this.sector = sector; 357 this.sector = sector;
358 }
359
360 public int getSector() {
361 return sector;
255 } 362 }
256 363
257 public boolean enlarge(SectorRange other) { 364 public boolean enlarge(SectorRange other) {
258 if (sector == other.sector 365 if (sector == other.sector
259 && Math.abs(end-other.start) < EPSILON2) { 366 && Math.abs(end-other.start) < EPSILON2) {
278 385
279 protected int columnId; 386 protected int columnId;
280 protected Date startTime; 387 protected Date startTime;
281 protected String name; 388 protected String name;
282 389
283 protected List<QRange> qRanges; 390 protected List<SectorRange> sectors;
284 391
285 public Column() { 392 public Column() {
286 } 393 }
287 394
288 public Column(int columnId, Date startTime, String name) { 395 public Column(int columnId, Date startTime, String name) {
289 this.columnId = columnId; 396 this.columnId = columnId;
290 this.startTime = startTime; 397 this.startTime = startTime;
291 this.name = name; 398 this.name = name;
292 399
293 qRanges = new ArrayList<QRange>(); 400 sectors = new ArrayList<SectorRange>();
294 } 401 }
295 402
296 public Fixing getFixing() { 403 public Fixing getFixing() {
297 return Fixing.this; 404 return Fixing.this;
298 } 405 }
299 406
300 public List<SectorRange> classify(GaugeRange gauge) { 407 public List<SectorRange> getSectors() {
301 408 return sectors;
302 List<SectorRange> sectors = new ArrayList<SectorRange>(); 409 }
410
411 public void buildSectors(GaugeRange gauge, List<QRange> qRanges) {
303 412
304 for (QRange qRange: qRanges) { 413 for (QRange qRange: qRanges) {
305 SectorRange sector = new SectorRange( 414 SectorRange sector = new SectorRange(
306 qRange.start, qRange.end, 415 qRange.start, qRange.end,
307 gauge.classify(qRange.q)); 416 gauge.classify(qRange.q));
308 if (sectors.isEmpty() 417 if (sectors.isEmpty()
309 || !sectors.get(sectors.size()-1).enlarge(sector)) { 418 || !sectors.get(sectors.size()-1).enlarge(sector)) {
310 sectors.add(sector); 419 sectors.add(sector);
311 } 420 }
312 } 421 }
313
314 return sectors;
315 } 422 }
316 423
317 public void loadKmRange(SQLQuery query) { 424 public void loadKmRange(SQLQuery query) {
318 query.setInteger("column_id", columnId); 425 query.setInteger("column_id", columnId);
319 426
327 start = (Double)obj[0]; 434 start = (Double)obj[0];
328 end = (Double)obj[1]; 435 end = (Double)obj[1];
329 } 436 }
330 } 437 }
331 438
332 public void loadQRanges(SQLQuery query) { 439 public void loadQRanges(
440 SQLQuery query,
441 GaugeFinder gaugeFinder
442 ) {
333 query.setInteger("column_id", columnId); 443 query.setInteger("column_id", columnId);
334 List<Object []> list = query.list(); 444 List<Object []> list = query.list();
445
446 List<QRange> qRanges = new ArrayList<QRange>(list.size());
335 447
336 for (Object [] row: list) { 448 for (Object [] row: list) {
337 double q = (Double)row[0]; 449 double q = (Double)row[0];
338 double start = (Double)row[1]; 450 double start = (Double)row[1];
339 double end = (Double)row[2]; 451 double end = (Double)row[2];
340 QRange qRange = new QRange(start, end, q); 452 QRange qRange = new QRange(start, end, q);
341 if (qRange.clip(this)) { 453 if (qRange.clip(this)) {
342 qRanges.add(qRange); 454 qRanges.add(qRange);
343 } 455 }
344 } 456 }
457
458 GaugeRange gauge = gaugeFinder.find(this);
459
460 if (gauge != null) {
461 buildSectors(gauge, qRanges);
462 }
463 else {
464 log.warn("No gauge found for column " + columnId + ".");
465 }
345 } 466 }
346 } // class Column 467 } // class Column
347 468
348 protected int wstId; 469 protected int wstId;
349 protected String description; 470 protected String description;
350 protected List<Column> columns; 471 protected List<Column> columns;
351 472
352 public Fixing() { 473 public Fixing() {
353 } 474 }
354 475
373 for (Column column: columns) { 494 for (Column column: columns) {
374 column.loadKmRange(query); 495 column.loadKmRange(query);
375 } 496 }
376 } 497 }
377 498
378 public void loadColumnsQRanges(SQLQuery query) { 499 public void loadColumnsQRanges(
500 SQLQuery query,
501 GaugeFinder gaugeFinder
502 ) {
379 for (Column column: columns) { 503 for (Column column: columns) {
380 column.loadQRanges(query); 504 column.loadQRanges(query, gaugeFinder);
381 } 505 }
382 } 506 }
383 507
384 public void addAllColumns(List<Column> allColumns) { 508 public void addAllColumns(List<Column> allColumns, Range range) {
385 allColumns.addAll(columns); 509 for (Column column: columns) {
510 if (column.intersects(range)) {
511 allColumns.add(column);
512 }
513 }
386 } 514 }
387 } // class Fixing 515 } // class Fixing
388 516
389 517
390 protected String riverName; 518 protected String riverName;
391 protected int riverId; 519 protected int riverId;
392 protected boolean isKmUp; 520 protected boolean isKmUp;
393 protected List<GaugeRange> gauges; 521 protected List<Fixing> fixings;
394 protected List<Fixing> fixings; 522 protected Range extent;
395 protected Range extent;
396 523
397 public FixingsOverview() { 524 public FixingsOverview() {
398 gauges = new ArrayList<GaugeRange>();
399 fixings = new ArrayList<Fixing>(); 525 fixings = new ArrayList<Fixing>();
400 } 526 }
401 527
402 public FixingsOverview(String riverName) { 528 public FixingsOverview(String riverName) {
403 this(); 529 this();
444 extent = new Range((Double)row[0], (Double)row[1]); 570 extent = new Range((Double)row[0], (Double)row[1]);
445 571
446 return true; 572 return true;
447 } 573 }
448 574
449 575 protected GaugeFinder loadGauges(Session session) {
450 protected boolean loadGauges(Session session) {
451 SQLQuery query = session.createSQLQuery(SQL_GAUGES) 576 SQLQuery query = session.createSQLQuery(SQL_GAUGES)
452 .addScalar("gauge_id", StandardBasicTypes.INTEGER) 577 .addScalar("gauge_id", StandardBasicTypes.INTEGER)
453 .addScalar("a", StandardBasicTypes.DOUBLE) 578 .addScalar("a", StandardBasicTypes.DOUBLE)
454 .addScalar("b", StandardBasicTypes.DOUBLE); 579 .addScalar("b", StandardBasicTypes.DOUBLE);
455 580
457 582
458 List<Object []> list = query.list(); 583 List<Object []> list = query.list();
459 584
460 if (list.isEmpty()) { 585 if (list.isEmpty()) {
461 log.warn("River " + riverId + " has no gauges."); 586 log.warn("River " + riverId + " has no gauges.");
462 return false; 587 return null;
463 } 588 }
589
590 List<GaugeRange> gauges = new ArrayList<GaugeRange>();
464 591
465 for (Object [] row: list) { 592 for (Object [] row: list) {
466 int gaugeId = (Integer)row[0]; 593 int gaugeId = (Integer)row[0];
467 double start = (Double) row[1]; 594 double start = (Double) row[1];
468 double end = (Double) row[2]; 595 double end = (Double) row[2];
469 GaugeRange gauge = new GaugeRange(start, end, gaugeId); 596 GaugeRange gauge = new GaugeRange(start, end, gaugeId);
470 gauges.add(gauge); 597 gauges.add(gauge);
471 } 598 }
472 599
473 return true; 600 return new GaugeFinder(gauges, isKmUp);
474 } 601 }
475 602
476 protected GaugeRange findGaugeById(int gaugeId) {
477 for (GaugeRange gauge: gauges) {
478 if (gauge.gaugeId == gaugeId) {
479 return gauge;
480 }
481 }
482 return null;
483 }
484
485 protected GaugeRange findGaugeByKm(double km) {
486 for (GaugeRange gauge: gauges) {
487 if (gauge.inside(km)) {
488 return gauge;
489 }
490 }
491 return null;
492 }
493
494 protected boolean loadDischargeSectors(Session session) {
495
496 SQLQuery query = session.createSQLQuery(SQL_DISCHARGE_SECTORS)
497 .addScalar("gauge_id", StandardBasicTypes.INTEGER)
498 .addScalar("name", StandardBasicTypes.STRING)
499 .addScalar("value", StandardBasicTypes.DOUBLE);
500
501 query.setInteger("river_id", riverId);
502
503 List<Object []> list = query.list();
504
505 if (list.isEmpty()) {
506 log.warn("River " + riverId + " has no discharge sectors.");
507 return false;
508 }
509
510 GaugeRange gauge = null;
511
512 for (Object [] row: list) {
513 int gaugeId = (Integer)row[0];
514 String label = (String) row[1];
515 Double value = (Double) row[2];
516
517 if (gauge == null || gauge.gaugeId != gaugeId) {
518 if ((gauge = findGaugeById(gaugeId)) == null) {
519 log.warn("Cannot find gauge for id " + gaugeId + ".");
520 continue;
521 }
522 }
523
524 gauge.addMainValue(label, value);
525 }
526
527 for (GaugeRange g: gauges) {
528 g.buildClasses();
529 }
530
531 return true;
532 }
533 603
534 protected void loadFixings(Session session) { 604 protected void loadFixings(Session session) {
535 SQLQuery query = session.createSQLQuery(SQL_FIXINGS) 605 SQLQuery query = session.createSQLQuery(SQL_FIXINGS)
536 .addScalar("wst_id", StandardBasicTypes.INTEGER) 606 .addScalar("wst_id", StandardBasicTypes.INTEGER)
537 .addScalar("description", StandardBasicTypes.STRING); 607 .addScalar("description", StandardBasicTypes.STRING);
572 for (Fixing fixing: fixings) { 642 for (Fixing fixing: fixings) {
573 fixing.loadColumnsKmRange(query); 643 fixing.loadColumnsKmRange(query);
574 } 644 }
575 } 645 }
576 646
577 protected void loadFixingsColumnsQRanges(Session session) { 647 protected void loadFixingsColumnsQRanges(
648 Session session,
649 GaugeFinder gaugeFinder
650 ) {
578 SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES) 651 SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES)
579 .addScalar("q", StandardBasicTypes.DOUBLE) 652 .addScalar("q", StandardBasicTypes.DOUBLE)
580 .addScalar("start_km", StandardBasicTypes.DOUBLE) 653 .addScalar("start_km", StandardBasicTypes.DOUBLE)
581 .addScalar("stop_km", StandardBasicTypes.DOUBLE); 654 .addScalar("stop_km", StandardBasicTypes.DOUBLE);
582 655
583 for (Fixing fixing: fixings) { 656 for (Fixing fixing: fixings) {
584 fixing.loadColumnsQRanges(query); 657 fixing.loadColumnsQRanges(query, gaugeFinder);
585 } 658 }
586 } 659 }
587 660
588 public boolean load(Session session) { 661 public boolean load(Session session) {
589 662
590 if (!loadRiver(session)) { 663 if (!loadRiver(session)
664 || !loadRiverExtent(session)) {
591 return false; 665 return false;
592 } 666 }
593 667
594 if (!loadRiverExtent(session)) { 668 GaugeFinder gaugeFinder = loadGauges(session);
595 return false; 669
596 } 670 if (gaugeFinder == null
597 671 || !gaugeFinder.loadDischargeSectors(session, riverId)) {
598 if (!loadGauges(session)) {
599 return false;
600 }
601
602 if (!loadDischargeSectors(session)) {
603 return false; 672 return false;
604 } 673 }
605 674
606 loadFixings(session); 675 loadFixings(session);
607 loadFixingsColumns(session); 676 loadFixingsColumns(session);
608 loadFixingsColumnsKmRange(session); 677 loadFixingsColumnsKmRange(session);
609 loadFixingsColumnsQRanges(session); 678 loadFixingsColumnsQRanges(session, gaugeFinder);
610 679
611 return true; 680 return true;
612 } 681 }
613 682
683 private static final Range FULL_EXTENT =
684 new Range(-Double.MAX_VALUE, Double.MAX_VALUE);
685
614 public void generateOverview(Document document) { 686 public void generateOverview(Document document) {
687 generateOverview(document, FULL_EXTENT);
688 }
689
690 public void generateOverview(Document document, Range range) {
615 691
616 List<Fixing.Column> allColumns = new ArrayList<Fixing.Column>(); 692 List<Fixing.Column> allColumns = new ArrayList<Fixing.Column>();
617 693
618 for (Fixing fixing: fixings) { 694 for (Fixing fixing: fixings) {
619 fixing.addAllColumns(allColumns); 695 fixing.addAllColumns(allColumns, range);
620 } 696 }
621 697
622 Collections.sort(allColumns, Fixing.DATE_CMP); 698 Collections.sort(allColumns, Fixing.DATE_CMP);
623 699
624 Element fixingsElement = document.createElement("fixings"); 700 Element fixingsElement = document.createElement("fixings");
635 711
636 Element esE = document.createElement("events"); 712 Element esE = document.createElement("events");
637 713
638 for (Fixing.Column column: allColumns) { 714 for (Fixing.Column column: allColumns) {
639 715
640 double km = isKmUp ? column.start : column.end; 716 // TODO: Apply additional filters here.
641 717 List<SectorRange> sectors = column.getSectors();
642 GaugeRange gauge = findGaugeByKm(km);
643
644 if (gauge == null) {
645 log.warn("Cannot find gauge for km " + km + ".");
646 continue;
647 }
648
649 List<SectorRange> sectors = column.classify(gauge);
650 718
651 if (!sectors.isEmpty()) { 719 if (!sectors.isEmpty()) {
652 Element eE = document.createElement("event"); 720 Element eE = document.createElement("event");
653 eE.setAttribute("name", 721 eE.setAttribute("name",
654 String.valueOf(column.getFixing().description)); 722 String.valueOf(column.getFixing().description));

http://dive4elements.wald.intevation.org