<commit_before>/*
 * USER: mslm
 * DATE: 3/31/2017
 */

package com.gedder.gedderalarm;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.gedder.gedderalarm.model.GedderEngine;
import com.gedder.gedderalarm.util.TimeUtilities;

import java.util.ArrayList;


/**
 * <p>Serves as the entry point for the Gedder algorithm.</p>
 *
 * <p>After gathering data from the intent that was broadcast, it starts up the
 * {@link GedderEngine}. The {@link GedderEngine} sends back some of the relevant data after flowing
 * through its pipeline.</p>
 *
 * <p>It then analyzes the response from the {@link GedderEngine}.</p>
 *
 * <p>During and after the analysis of the result data, it determines what action to take. It may do
 * one of the following:</p>
 *
 * <ul>
 *     <li>Reschedule itself to start up the {@link GedderEngine} for some default set time in the
 *     future.</li>
 *     <li>Reschedule itself to start up the {@link GedderEngine} for some adjusted time in the
 *     future.</li>
 *     <li>Trigger the alarm.</li>
 * </ul><br>
 *
 * <u><strong>Case 1</strong></u>
 *
 * <p>In the first case, the algorithm sees no reason for concern, and just carries on rescheduling
 * itself for future analysis at some default rate.</p>
 *
 * <u><strong>Case 2</strong></u>
 *
 * <p>In the second case, the algorithm picks up a possible delay, but it is not urgent enough that
 * the user needs to wake up right now. It'll reschedule itself for future analysis, but at a
 * tighter bound (how much tighter depends on the severity of the delay relative to the "wish"
 * alarm time).</p>
 *
 * <u><strong>Case 3</strong></u>
 *
 * <p>In the last case, the algorithm makes the decision to wake the user up right away: it caught a
 * delay significant enough that if the user doesn't take action now, they'll be late to their
 * destination.</p>
 *
 * <p>Each time the algorithm sets itself up for a future flow through the pipeline, it checks how
 * close it is to the currently planned alarm time. The closer it gets, the more often it queries
 * for updates on traffic and possible delays. This carries on until the algorithm notices that
 * now the user must wake up as soon as possible, otherwise the delay can be detrimental to reaching
 * the destination at the planned arrival time.</p>
 *
 * <p>To sum, the algorithm can either reschedule itself for a default rate of analysis, or a
 * tighter rate, or trigger the alarm, all depending on information it has previously received and
 * analyzed.</p>
 *
 * <p>In this way, the algorithm ensures it's awake and aware of any delays at all times, and
 * becomes increasingly active when there's a concern, i.e. when delays are present.</p>
 */

public class GedderReceiver extends BroadcastReceiver {
    private static final String TAG = GedderReceiver.class.getSimpleName();

    public static final String PARAM_ORIGIN = "__PARAM_ORIGIN__";
    public static final String PARAM_DESTINATION = "__PARAM_DESTINATION__";
    public static final String PARAM_ARRIVAL_TIME = "__PARAM_ARRIVAL_TIME__";
    public static final String PARAM_PREP_TIME = "__PARAM_PREP_TIME__";
    public static final String PARAM_UPPER_BOUND_TIME = "__PARAM_UPPER_BOUND_TIME__";
    public static final String PARAM_ID = "__PARAM_ID__";

    @Override
    public void onReceive(Context context, Intent intent) {
        String origin         = intent.getStringExtra(PARAM_ORIGIN);
        String dest           = intent.getStringExtra(PARAM_DESTINATION);
        long   arrivalTime    = intent.getLongExtra(PARAM_ARRIVAL_TIME, -1);
        long   prepTime       = intent.getLongExtra(PARAM_PREP_TIME, -1);
        long   upperBoundTime = intent.getLongExtra(PARAM_UPPER_BOUND_TIME, -1);
        int    id             = intent.getIntExtra(PARAM_ID, -1);

        if (origin == null || dest == null
                || origin.equals("") || dest.equals("")
                || arrivalTime == -1 || prepTime == -1 || upperBoundTime == -1
                || id == -1) {
            throw new IllegalArgumentException("origin = " + origin
                            + " dest = " + dest
                            + " arrivalTime = " + arrivalTime
                            + " prepTime = " + prepTime
                            + " upperBoundTime = " + upperBoundTime
                            + " id = " + id);
        }

        // Turn on the engine, and get back the results.
        Bundle results = GedderEngine.start(origin, dest, arrivalTime);
        long duration = TimeUtilities.secondsToMillis(
                results.getInt(GedderEngine.RESULT_DURATION, -1));
        long durationInTraffic = TimeUtilities.secondsToMillis(
                results.getInt(GedderEngine.RESULT_DURATION_IN_TRAFFIC, -1));
        @SuppressWarnings("unchecked")
        ArrayList<String> warnings = (ArrayList<String>)
                results.getSerializable(GedderEngine.RESULT_WARNINGS);

        // Need this for a comprehensible analysis below.
        long optimalWakeUpTime = arrivalTime - duration - prepTime;
        long timeUntilAlarm    = upperBoundTime - System.currentTimeMillis();

        // Initialize & declare intents and variables for our next action.
        Intent next = new Intent(GedderAlarmApplication.getAppContext(), GedderReceiver.class);
        long nextTime;

        if (System.currentTimeMillis() > optimalWakeUpTime) {
            // Wake up the user!
            next.setClass(GedderAlarmApplication.getAppContext(), AlarmReceiver.class);
            nextTime = System.currentTimeMillis() + TimeUtilities.secondsToMillis(1);
        } else {
            // Check back in a time dependent on how close we are to the alarm time.
            nextTime = System.currentTimeMillis() + getFrequencyDependingOn(timeUntilAlarm);
        }

        // Whatever the analysis, we must set the intent.
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                GedderAlarmApplication.getAppContext(), id, next, PendingIntent.FLAG_UPDATE_CURRENT);
        GedderAlarmManager.setOptimal(
                AlarmManager.RTC_WAKEUP, nextTime, pendingIntent);
    }

    /**
     * Returns a requery frequency depending upon some time.
     * <br><commit_msg>The gedder algorithm will take into account the user desired wish time.<commit_after>/*
 * USER: mslm
 * DATE: 3/31/2017
 */

package com.gedder.gedderalarm;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.gedder.gedderalarm.model.GedderEngine;
import com.gedder.gedderalarm.util.TimeUtilities;

import java.util.ArrayList;


/**
 * <p>Serves as the entry point for the Gedder algorithm.</p>
 *
 * <p>After gathering data from whatever started up this activity, it starts up the
 * {@link GedderEngine}. The {@link GedderEngine} sends back some of the relevant data after flowing
 * through its pipeline. It then analyzes the response.</p>
 *
 * <p>From going through the analysis, it determines what action to take. It may either:</p>
 *
 * <ul>
 *     <li>Reschedule itself to start the {@link GedderEngine} up for some time in the future
 *     depending on how much time we have until the alarm.</li>
 *     <li>Trigger the alarm.</li>
 * </ul><br>
 *
 * <u><strong>Case 1</strong></u>
 *
 * <p>In the first case, the algorithm sees no reason for concern, and just carries on rescheduling
 * itself for future analysis at some rate it determines based off of how much time there currently
 * is until the alarm is supposed to ring.</p>
 *
 * <u><strong>Case 2</strong></u>
 *
 * <p>In the second case, the algorithm picks up a possible delay, but it is not urgent enough that
 * the user needs to wake up right now. It'll reschedule itself for future analysis, but at a
 * tighter bound (how much tighter depends on the severity of the delay relative to the "wish"
 * alarm time).</p>
 *
 * <u><strong>Case 3</strong></u>
 *
 * <p>In the last case, the algorithm makes the decision to wake the user up right away: it caught a
 * delay significant enough that if the user doesn't take action now, they'll be late to their
 * destination.</p>
 *
 * <p>Each time the algorithm sets itself up for a future flow through the pipeline, it checks how
 * close it is to the currently planned alarm time. The closer it gets, the more often it queries
 * for updates on traffic and possible delays. This carries on until the algorithm notices that
 * now the user must wake up as soon as possible, otherwise the delay can be detrimental to reaching
 * the destination at the planned arrival time.</p>
 *
 * <p>To sum, the algorithm can either reschedule itself for a default rate of analysis, or a
 * tighter rate, or trigger the alarm, all depending on information it has previously received and
 * analyzed.</p>
 *
 * <p>In this way, the algorithm ensures it's awake and aware of any delays at all times, and
 * becomes increasingly active when there's a concern, i.e. when delays are present.</p>
 */

public class GedderReceiver extends BroadcastReceiver {
    private static final String TAG = GedderReceiver.class.getSimpleName();

    public static final String PARAM_ORIGIN = "__PARAM_ORIGIN__";
    public static final String PARAM_DESTINATION = "__PARAM_DESTINATION__";
    public static final String PARAM_ARRIVAL_TIME = "__PARAM_ARRIVAL_TIME__";
    public static final String PARAM_PREP_TIME = "__PARAM_PREP_TIME__";
    public static final String PARAM_UPPER_BOUND_TIME = "__PARAM_UPPER_BOUND_TIME__";
    public static final String PARAM_ID = "__PARAM_ID__";

    @Override
    public void onReceive(Context context, Intent intent) {
        String origin         = intent.getStringExtra(PARAM_ORIGIN);
        String dest           = intent.getStringExtra(PARAM_DESTINATION);
        long   arrivalTime    = intent.getLongExtra(PARAM_ARRIVAL_TIME, -1);
        long   prepTime       = intent.getLongExtra(PARAM_PREP_TIME, -1);
        long   upperBoundTime = intent.getLongExtra(PARAM_UPPER_BOUND_TIME, -1);
        int    id             = intent.getIntExtra(PARAM_ID, -1);

        if (origin == null || dest == null
                || origin.equals("") || dest.equals("")
                || arrivalTime == -1 || prepTime == -1 || upperBoundTime == -1
                || id == -1) {
            throw new IllegalArgumentException("origin = " + origin
                            + " dest = " + dest
                            + " arrivalTime = " + arrivalTime
                            + " prepTime = " + prepTime
                            + " upperBoundTime = " + upperBoundTime
                            + " id = " + id);
        }

        // Turn on the engine, and get back the results.
        Bundle results = GedderEngine.start(origin, dest, arrivalTime);
        long duration = TimeUtilities.secondsToMillis(
                results.getInt(GedderEngine.RESULT_DURATION, -1));
        long durationInTraffic = TimeUtilities.secondsToMillis(
                results.getInt(GedderEngine.RESULT_DURATION_IN_TRAFFIC, -1));
        @SuppressWarnings("unchecked")
        ArrayList<String> warnings = (ArrayList<String>)
                results.getSerializable(GedderEngine.RESULT_WARNINGS);

        // Need this for a comprehensible analysis below.
        long optimalWakeUpTime = arrivalTime - duration - prepTime;
        long wishWakeUpTime    = arrivalTime - prepTime - upperBoundTime;
        long timeUntilAlarm    = optimalWakeUpTime - System.currentTimeMillis();

        // Initialize & declare intents and variables for our next action.
        Intent next = new Intent(GedderAlarmApplication.getAppContext(), GedderReceiver.class);
        long nextTime;

        if (System.currentTimeMillis() > optimalWakeUpTime
                || System.currentTimeMillis() > wishWakeUpTime) {
            // Wake up the user!
            next.setClass(GedderAlarmApplication.getAppContext(), AlarmReceiver.class);
            nextTime = System.currentTimeMillis() + TimeUtilities.secondsToMillis(1);
        } else {
            // Check back in a time dependent on how close we are to the alarm time.
            nextTime = System.currentTimeMillis() + getFrequencyDependingOn(timeUntilAlarm);
        }

        // Whatever the analysis, we must set the intent.
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                GedderAlarmApplication.getAppContext(), id, next, PendingIntent.FLAG_UPDATE_CURRENT);
        GedderAlarmManager.setOptimal(
                AlarmManager.RTC_WAKEUP, nextTime, pendingIntent);
    }

    /**
     * Returns a requery frequency depending upon some time.
     * <br>
{'fraction_non_alphanumeric': 0.08739521887612543, 'fraction_numerical': 0.003259857187208941, 'mean_word_length': 2.911657559198543, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 90, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6270207', 'n_tokens_mistral': 3554, 'n_tokens_neox': 3512, 'n_words': 1237}