Move some models

This commit is contained in:
2017-05-25 08:24:22 -04:00
parent f18ac9db48
commit d23b59ced2
8 changed files with 2 additions and 0 deletions

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import org.apache.commons.lang3.builder.*;
import javax.annotation.concurrent.*;
/**
* A Checkmark represents the completion status of the habit for a given day.
* <p>
* While repetitions simply record that the habit was performed at a given date,
* a checkmark provides more information, such as whether a repetition was
* expected at that day or not.
* <p>
* Checkmarks are computed automatically from the list of repetitions.
*/
@ThreadSafe
public final class Checkmark
{
/**
* Indicates that there was a repetition at the timestamp.
*/
public static final int CHECKED_EXPLICITLY = 2;
/**
* Indicates that there was no repetition at the timestamp, but one was not
* expected in any case, due to the frequency of the habit.
*/
public static final int CHECKED_IMPLICITLY = 1;
/**
* Indicates that there was no repetition at the timestamp, even though a
* repetition was expected.
*/
public static final int UNCHECKED = 0;
private final long timestamp;
/**
* The value of the checkmark.
*
* For boolean habits, this equals either UNCHECKED, CHECKED_EXPLICITLY,
* or CHECKED_IMPLICITLY.
*
* For numerical habits, this number is stored in thousandths. That
* is, if the user enters value 1.50 on the app, it is stored as 1500.
*/
private final int value;
public Checkmark(long timestamp, int value)
{
this.timestamp = timestamp;
this.value = value;
}
public int compareNewer(Checkmark other)
{
return Long.signum(this.getTimestamp() - other.getTimestamp());
}
public long getTimestamp()
{
return timestamp;
}
public int getValue()
{
return value;
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("timestamp", timestamp)
.append("value", value)
.toString();
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import org.apache.commons.lang3.builder.*;
import javax.annotation.concurrent.*;
/**
* Represents how often is the habit repeated.
*/
@ThreadSafe
public class Frequency
{
public static final Frequency DAILY = new Frequency(1, 1);
public static final Frequency FIVE_TIMES_PER_WEEK = new Frequency(5, 7);
public static final Frequency THREE_TIMES_PER_WEEK = new Frequency(3, 7);
public static final Frequency TWO_TIMES_PER_WEEK = new Frequency(2, 7);
public static final Frequency WEEKLY = new Frequency(1, 7);
private final int numerator;
private final int denominator;
public Frequency(int numerator, int denominator)
{
if (numerator == denominator) numerator = denominator = 1;
this.numerator = numerator;
this.denominator = denominator;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Frequency frequency = (Frequency) o;
return new EqualsBuilder()
.append(numerator, frequency.numerator)
.append(denominator, frequency.denominator)
.isEquals();
}
public int getDenominator()
{
return denominator;
}
public int getNumerator()
{
return numerator;
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(numerator)
.append(denominator)
.toHashCode();
}
public double toDouble()
{
return (double) numerator / denominator;
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("numerator", numerator)
.append("denominator", denominator)
.toString();
}
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import java.util.*;
import javax.annotation.concurrent.*;
/**
* A ModelObservable allows objects to subscribe themselves to it and receive
* notifications whenever the model is changed.
*/
@ThreadSafe
public class ModelObservable
{
private List<Listener> listeners;
/**
* Creates a new ModelObservable with no listeners.
*/
public ModelObservable()
{
super();
listeners = new LinkedList<>();
}
/**
* Adds the given listener to the observable.
*
* @param l the listener to be added.
*/
public synchronized void addListener(Listener l)
{
listeners.add(l);
}
/**
* Notifies every listener that the model has changed.
* <p>
* Only models should call this method.
*/
public synchronized void notifyListeners()
{
for (Listener l : listeners) l.onModelChange();
}
/**
* Removes the given listener.
* <p>
* The listener will no longer be notified when the model changes. If the
* given listener is not subscribed to this observable, does nothing.
*
* @param l the listener to be removed
*/
public synchronized void removeListener(Listener l)
{
listeners.remove(l);
}
/**
* Interface implemented by objects that want to be notified when the model
* changes.
*/
public interface Listener
{
/**
* Called whenever the model associated to this observable has been
* modified.
*/
void onModelChange();
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import android.support.annotation.*;
public final class Reminder
{
private final int hour;
private final int minute;
private final WeekdayList days;
public Reminder(int hour, int minute, @NonNull WeekdayList days)
{
this.hour = hour;
this.minute = minute;
this.days = days;
}
@NonNull
public WeekdayList getDays()
{
return days;
}
public int getHour()
{
return hour;
}
public int getMinute()
{
return minute;
}
}

View File

@@ -1,99 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import org.apache.commons.lang3.builder.*;
/**
* Represents a record that the user has performed a certain habit at a certain
* date.
*/
public final class Repetition
{
private final long timestamp;
/**
* The value of the repetition.
*
* For boolean habits, this equals either Checkmark.UNCHECKED,
* Checkmark.CHECKED_EXPLICITLY, or Checkmark.CHECKED_IMPLICITLY.
*
* For numerical habits, this number is stored in thousandths. That
* is, if the user enters value 1.50 on the app, it is stored as 1500.
*/
private final int value;
/**
* Creates a new repetition with given parameters.
* <p>
* The timestamp corresponds to the days this repetition occurred. Time of
* day must be midnight (UTC).
*
* @param timestamp the time this repetition occurred.
*/
public Repetition(long timestamp, int value)
{
this.timestamp = timestamp;
this.value = value;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Repetition that = (Repetition) o;
return new EqualsBuilder()
.append(timestamp, that.timestamp)
.append(value, that.value)
.isEquals();
}
public long getTimestamp()
{
return timestamp;
}
public int getValue()
{
return value;
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(timestamp)
.append(value)
.toHashCode();
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("timestamp", timestamp)
.append("value", value)
.toString();
}
}

View File

@@ -1,96 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import org.apache.commons.lang3.builder.*;
import static java.lang.Math.*;
/**
* Represents how strong a habit is at a certain date.
*/
public final class Score
{
/**
* Timestamp of the day to which this score applies. Time of day should be
* midnight (UTC).
*/
private final long timestamp;
/**
* Value of the score.
*/
private final double value;
public Score(long timestamp, double value)
{
this.timestamp = timestamp;
this.value = value;
}
/**
* Given the frequency of the habit, the previous score, and the value of
* the current checkmark, computes the current score for the habit.
* <p>
* The frequency of the habit is the number of repetitions divided by the
* length of the interval. For example, a habit that should be repeated 3
* times in 8 days has frequency 3.0 / 8.0 = 0.375.
*
* @param frequency the frequency of the habit
* @param previousScore the previous score of the habit
* @param checkmarkValue the value of the current checkmark
* @return the current score
*/
public static double compute(double frequency,
double previousScore,
double checkmarkValue)
{
double multiplier = pow(0.5, frequency / 13.0);
double score = previousScore * multiplier;
score += checkmarkValue * (1 - multiplier);
return score;
}
public int compareNewer(Score other)
{
return Long.signum(this.getTimestamp() - other.getTimestamp());
}
public long getTimestamp()
{
return timestamp;
}
public double getValue()
{
return value;
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("timestamp", timestamp)
.append("value", value)
.toString();
}
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.models;
import java.util.*;
public class WeekdayList
{
public static final WeekdayList EVERY_DAY = new WeekdayList(127);
private final boolean[] weekdays;
public WeekdayList(int packedList)
{
weekdays = new boolean[7];
int current = 1;
for (int i = 0; i < 7; i++)
{
if ((packedList & current) != 0) weekdays[i] = true;
current = current << 1;
}
}
public WeekdayList(boolean weekdays[])
{
this.weekdays = Arrays.copyOf(weekdays, 7);
}
public boolean isEmpty()
{
for (boolean d : weekdays) if (d) return false;
return true;
}
public boolean[] toArray()
{
return Arrays.copyOf(weekdays, 7);
}
public int toInteger()
{
int packedList = 0;
int current = 1;
for (int i = 0; i < 7; i++)
{
if (weekdays[i]) packedList |= current;
current = current << 1;
}
return packedList;
}
}