| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package io.v.android.apps.syncslides.discovery; |
| |
| import android.util.Log; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import io.v.android.apps.syncslides.model.Participant; |
| |
| /** |
| * Moderator is a task that figures out who's presenting. |
| * |
| * On each call to run(), it scans a MT for information about participant |
| * services, then contacts those participants for information on what they are |
| * presenting. When a scan is complete, it calls mObserver.onTaskDone(). |
| * |
| * Not safe for more than one thread to enter run() at a time. |
| */ |
| class Moderator implements Runnable { |
| |
| private static final String TAG = "Moderator"; |
| |
| // Participants that appeared for the first time in the most recent scan. |
| private final Set<Participant> mFreshman = new HashSet<>(); |
| |
| // Participants seen currently present for more than one scan. |
| private final Set<Participant> mSenior = new HashSet<>(); |
| |
| // Participants that were not seen in the most recent scan, but we there in |
| // the scan just before that. |
| private final Set<Participant> mGraduated = new HashSet<>(); |
| // Does the actual scan. |
| private final ParticipantScanner mScanner; |
| // Notify this guy when task done; make it a list if more needed. |
| private Observer mObserver; |
| |
| public Moderator(ParticipantScanner scanner) { |
| mScanner = scanner; |
| } |
| |
| public void setObserver(Observer observer) { |
| this.mObserver = observer; |
| } |
| |
| public Set<Participant> getGraduated() { |
| return mGraduated; |
| } |
| |
| public Set<Participant> getFreshman() { |
| return mFreshman; |
| } |
| |
| @Override |
| public void run() { |
| if (mObserver == null) { |
| throw new IllegalStateException("Must have an observer."); |
| } |
| try { |
| process(mScanner.scan()); |
| mObserver.onTaskDone(); |
| } catch (Throwable t) { |
| Log.e(TAG, "Scan Failed.", t); |
| } |
| } |
| |
| private void process(Set<Participant> latest) { |
| Set<Participant> current = new HashSet<>(); |
| current.addAll(mSenior); |
| current.addAll(mFreshman); |
| |
| mSenior.clear(); |
| mFreshman.clear(); |
| |
| Set<Participant> potentials = new HashSet<>(); |
| |
| for (Participant p : latest) { |
| if (current.contains(p)) { |
| mSenior.add(p); |
| } else { |
| potentials.add(p); |
| } |
| } |
| |
| mGraduated.clear(); |
| for (Participant p : current) { |
| if (!latest.contains(p)) { |
| mGraduated.add(p); |
| } |
| } |
| |
| |
| for (Participant p : potentials) { |
| if (p.refreshData()) { |
| mFreshman.add(p); |
| } |
| } |
| } |
| |
| public interface Observer { |
| void onTaskDone(); |
| } |
| } |