niedziela, marca 10, 2013

SleepAdvisor - komórka pomaga w wyspaniu się ;-)

Chcę popełnić prosty programik, który sobie weźmie od Androida czas następnego alarmu i policzy mi o której powinienem pójść spać chcąc przespać odpowiedni czas.

Ten odpowiedni czas to wielokrotność 1.5 godziny + 30 minut +/- 15 minut.
Początkowo niech to będzie 4.5, 6, 7.5 i 9 godzin.

Banalne zadanie, ale takie nie do końca oczywiste ;-)

Następny alarm można dostać pytając o to system w taki sposób:
String nextAlarm = Settings.System.getString(getContentResolver(),Settings.System.NEXT_ALARM_FORMATTED);

Który to kawałek może zwrócić nam:
Mon 7:00 am
pon. 7:00
Mon 7:00

czyli skrócona nazwa dnia, wg. aktualnych ustawień systemu, godzina wg. aktualnych ustawień systemu...

Teraz drania trzeba przeliczyć na czas....
Na razie mam coś takiego:
private Date getNextAlarm() {
// let's collect short names of days :-)
DateFormatSymbols symbols = new DateFormatSymbols();
// and fill with those names map...
Map map = new HashMap();
String[] dayNames = symbols.getShortWeekdays();
// filing :-)
for (int i=1; i<dayNames.length; i++) {
int nextDay = (i+1)%7;
if (nextDay==0) nextDay=1;
map.put(dayNames[nextDay], i);
}
// Yeah, knowing next alarm will help.....
String nextAlarm = Settings.System.getString(getContentResolver(),Settings.System.NEXT_ALARM_FORMATTED);
// In case if it isn't set.....
if (nextAlarm==null) return null;
// let's see a day....
String nextAlarmDay = nextAlarm.split(" ")[0];
// and its number....
int alarmDay = map.get(nextAlarmDay);

// the same for day of week (I'm not sure why I didn't use Calendar.get(Calendar.DAY_OF_WEEK) here...
Date now = new Date();
String dayOfWeek = new SimpleDateFormat("EE", Locale.getDefault()).format(now);
int today = map.get(dayOfWeek);

// OK, so let's calculate how many days we have to next alarm :-)
int daysToAlarm = alarmDay-today;
// yep, sometimes it will be negtive number so add 7.
if (daysToAlarm<0) daysToAlarm+=7;
// Now we will build date, and parse it.....
try {
Calendar cal2 = Calendar.getInstance();
String str = cal2.get(Calendar.YEAR)+"-"+(cal2.get(Calendar.MONTH)+1)+"-"+(cal2.get(Calendar.DAY_OF_MONTH)+daysToAlarm);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-d hh:mm");
// and return it
return df.parse(str+nextAlarm.substring(nextAlarm.indexOf(" ")));
} catch (Exception e) {

}
// in case if we cannot calculate...
return null;
}

Wygląda  strasznie,  ale chociaż wydaje się zwracać to co powinno ;-) [komentarze dodałem coby się łatwiej czytało i by można było dostrzec "geniusz" rozwiązania ;-)]

Mając już odpowiedni czas łatwo policzyć czas kiedy trzeba by pójść spać:

Calendar cal = Calendar.getInstance();

for (int i=3; i<=6; i++) {
int minutes = i*90+30;
cal.setTime(nextAlarm);
cal.add(Calendar.MINUTE, -minutes);
System.out.println(i*90.0/60.0+" "+cal.getTime());
}

A oto wynik działania programu ;-)



Czyli w moim przypadku, jeśli chciałbym jutro wstać o 8:50 i spać 7.5 godziny powinienem pójść spać o 0:50 jutro.... co jest  mało prawdopodobne i zapewne pójdę spać bliżej 2:20 i prześpię 6 godzin (30 minut jest na zasypianie).... chociaż istnieje dość duże ryzyko, że pójdę spać o 3:50 i prześpię 4.5 godziny ;-)
Przez co jutro będę strasznie, ale to strasznie zły ;-)

Teraz trzeba tylko mój potworny programik uładnić i będę miał narzędzie na które od lat czekałem ;-)

[gdy zaczynałem pisać ten post jakieś 1.5 godziny temu to nic nie miałem,  teraz  mam programik :-)]



Podobne postybeta
ETA - liczymy szacowany czas zakończenia [przybycia ;-)]
Jak nie zapomnieć kupić biletu miesięcznego ;-)
Zinwigiluj się sam ;-)
Jak nie zapomnieć kupić biletu miesięcznego - revised ;-)
Google App Engine i DatastoreTimeoutException