Package com.google.silvercomet.client

Source Code of com.google.silvercomet.client.Model$Listener

// Copyright 2010 Google Inc. All Rights Reserved.

package com.google.silvercomet.client;

import com.google.gwt.xhr.client.XMLHttpRequest;

import elemental.client.Browser;
import elemental.html.Window;
import elemental.util.ArrayOf;
import elemental.util.ArrayOfInt;
import elemental.util.ArrayOfString;
import elemental.util.MapFromStringTo;
import elemental.json.Json;
import elemental.js.util.StringUtil;
import elemental.js.util.Xhr;
import elemental.util.CanCompare;
import elemental.dom.TimeoutHandler;
import elemental.util.Collections;

/**
* A very simple data model for the application.
*
* @author knorton@google.com (Kelly Norton)
*/
public class Model implements Xhr.Callback {

  /**
   * A listener to receive callbacks on model events.
   */
  public interface Listener {
    void modelDidFailLoading(Model model);

    void modelDidFinishBuildingIndex(Model model);

    void modelDidFinishLoading(Model model);
  }

  private static final String DATA_URL = "results.json";

  public static final int SECONDS_PER_HISTOGRAM_BUCKET = 600;

  /**
   * Compute a histogram with number of finishers per bucket of time where the
   * size of the bucket is indicated by <code>seconds</code>.
   */
  private static ArrayOfInt computeHistogram(ArrayOf<Runner> runners, int seconds) {
    final ArrayOfInt hist = Collections.arrayOfInt();

    for (int i = 0, n = runners.length(); i < n; ++i) {
      int index = runners.get(i).time() / seconds;
      hist.set(index, hist.isSet(index) ? hist.get(index) + 1 : 1);
    }

    int sum = 0;
    for (int i = 0, n = hist.length(); i < n; ++i) {
      if (hist.isSet(i)) {
        sum += hist.get(i);
      }
      hist.set(i, sum);
    }

    return hist;
  }

  /**
   * Sorts the list of runners by {@link Runner#time()} and updates their places
   * accordingly.
   */
  private static ArrayOf<Runner> normalize(ArrayOf<Runner> runners) {
    // Sort by time() which is based on bib time.
    runners.sort(new CanCompare<Runner>() {
      @Override
      public int compare(Runner a, Runner b) {
        return a.time() - b.time();
      }
    });

    // Update the runner's new place.
    for (int i = 0, n = runners.length(); i < n; ++i) {
      runners.get(i).setPlace(i + 1);
    }

    return runners;
  }

  /**
   * Update the model's index with all possible prefixes of the search key.
   */
  private static void updateIndexForAllPrefixes(
      MapFromStringTo<ArrayOf<Runner>> index, String key, Runner runner) {
    assert key.length() > 0 : "key.length must be > 0.";

    for (int i = 1, n = key.length(); i <= n; ++i) {
      final String prefix = key.substring(0, i);
      if (!index.hasKey(prefix)) {
        index.put(prefix, Collections.<Runner>arrayOf());
      }

      final ArrayOf<Runner> values = index.get(prefix);
      // Do not add the same runner twice.
      if (values.get(values.length() - 1) != runner) {
        index.get(prefix).push(runner);
      }
    }
  }

  private final Listener listener;

  private ArrayOfInt histogram = null;

  private MapFromStringTo<ArrayOf<Runner>> index = Collections.mapFromStringTo();

  /**
   * Create a new model.
   */
  public Model(Listener listener) {
    this.listener = listener;
  }

  /**
   * Get a reference to the models histogram.
   */
  public ArrayOfInt histogram() {
    return histogram;
  }

  /**
   * Load the remote data into the model.
   */
  public void load() {
    Xhr.get(DATA_URL, this);
  }

  /**
   * Called if the XHR fails to load data from there server.
   */
  @Override
  public void onFail(XMLHttpRequest xhr) {
    listener.modelDidFailLoading(this);
  }

  /**
   * Called when XHR successfully loads data from the server.
   */
  @Override
  public void onSuccess(XMLHttpRequest xhr) {
    update((ArrayOf<Runner>)Json.parse(xhr.getResponseText()));
    listener.modelDidFinishLoading(this);
  }

  /**
   * Performs a search and returns the list of runners that match.
   */
  public ArrayOf<Runner> search(String query) {
    return index.get(query);
  }

  /**
   * Update the model's internal data from an list of runners coming from the
   * server.
   */
  private void update(ArrayOf<Runner> data) {
    // Sort & mutate source data.
    final ArrayOf<Runner> runners = normalize(data);

    // Update indexes later.
    Browser.getWindow().setTimeout(new TimeoutHandler() {
      @Override
      public void onTimeoutHandler() {
        for (int i = 0, n = runners.length(); i < n; ++i) {
          final Runner runner = runners.get(i);

          final String name = runner.name().toLowerCase();
          updateIndexForAllPrefixes(index, name, runner);
          final ArrayOfString words = StringUtil.split(name, " ");
          for (int j = 0, m = words.length(); j < m; ++j) {
            updateIndexForAllPrefixes(index, words.get(j), runner);
          }

          updateIndexForAllPrefixes(index, "" + runner.place(), runner);
          updateIndexForAllPrefixes(index, "" + runner.bibNumber(), runner);
        }
        listener.modelDidFinishBuildingIndex(Model.this);
      }
    }, 0);

    // Compute histogram.
    final ArrayOfInt histogram = computeHistogram(runners, SECONDS_PER_HISTOGRAM_BUCKET);

    // Update fields.
    this.histogram = histogram;
  }
}
TOP

Related Classes of com.google.silvercomet.client.Model$Listener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.