Sehr geehrter Herr Lammers, hier nun die vorlaeufige Endversion des Projekts "TimeSlice". Aus Zeitgruenden war eine konkrete Ausarbeitung in JAVA nicht mehr moeglich. Stattdessen folgt eine Implementation in Pseudocode der Hauptschleife. Da die Algorithmen des Jobeditierens trivial sind, wurden sie nicht mit aufgenommen. Das Pflichtenheft selbst ist im Vergleich zur vorhergehenden Version unveraendert. Es dient hier nur der Buendelung mit den neuen Daten zu einem Gesamtpaket. Pflichtenheft "Time Slice": =========================== 1. Zielbestimmung Bei "Time Slice" soll es sich um ein Werkzeug handeln, welches der Zeiteinteilung/ Abarbeitung von Zeitzuteilungen (sogenannten "Zeitscheiben") fuer verschiedene Aufgaben dient. 1.1 Muss-Bestimmung 1.1.1 Zeitscheiben muessen automatisch aktualisiert werden. 1.1.2 Aufgaben muessen editiert und geloescht werden. 1.1.3 Die graphische Oberflaeche muss leicht zu bedienen sein. 1.1.4 Es muss stets eine aktuelle graphische Darstellung der Zeitreste ausgegeben werden. 1.2 Kann-Bestimmung 1.2.1 Unter Umstaenden sollte ein Signalton bei besonderer Dringlichkeit ertoenen. 1.3 Abgrenzung -- 2. Produkteinsatz 2.1 Anwendungsbereich Das Programm sollte an einem beliebigen Standardarbeitsplatz auf dem jeweiligen Arbeitsrechner betrieben werden koennen. 2.2 Zielgruppen Als Zielgruppe kommen z. B. Zeitarbeiter in Frage, allgemein Leute mit wenig Zeit. 2.3 Betriebsbedingungen -- 3. Produktumgebung 3.1 Software Als vorauszusetzende Software muss ein Browser (z. B. Netscape, MS-Explorer) auf dem Arbeitsplatzrechner installiert sein. 3.2 Hardware Besondere Bedingungen an die Hardware werden nicht gestellt, da das zu erstellende Werkzeug innerhalb des Browsers, und damit auf jedem Standardrechner, der ueber einen Browser verfuegt, ablaufen soll. 3.3 Orgware -- 3.4 Schnittstellen -- 4. Produktfunktion 4.1 Aufgabe hinzufuegen o /--------------------\ /|\ _______| Aufgabe hinzufuegen |__________________ / \ \--------------------/ \ | << uses >> | << uses >> \|/ \|/ /----------------------\ /--------------------\ | Aufgabe deaktivieren | | Aufgabe aktivieren | \----------------------/ \--------------------/ Akteur: Benutzer Ablauf: Der aktuelle Job wird deaktiviert. Der Benutzer gibt die Angaben der neuen Aufgabe ein. Der aktuelle Job wird aktiviert. (Der veraenderte Job muss nicht automatisch zum aktuellen Job werden.) Nachbedingung: Der Job wird in die Liste der Jobs aufgenommen. Ausnahme: 1. Der Job ist schon vorhanden. ==> Fehlermeldung an den Benutzer 2. Die Zeitangabe ist inkorrekt. ==> Fehlermeldung an den Benutzer 3. Es existieren zu viele Jobs. ==> Fehlermeldung an den Benutzer 4.2 Aufgabe editieren o /--------------------\ /|\ _______| Aufgabe editieren |__________________ / \ \--------------------/ \ | << uses >> | << uses >> \|/ \|/ /----------------------\ /--------------------\ | Aufgabe deaktivieren | | Aufgabe aktivieren | \----------------------/ \--------------------/ Akteur: Benutzer Ablauf: Der aktuelle Job wird deaktiviert. Der Benutzer gibt die neuen Angaben der Aufgabe ein. Der aktuelle Job wird aktiviert. (Der veraenderte Job muss nicht automatisch zum aktuellen Job werden.) Nachbedingung: -- Ausnahme: Die Zeitangabe ist inkorrekt. ==> Fehlermeldung an den Benutzer 4.3 Aufgabe aktivieren o /--------------------\ /|\ _______| Aufgabe aktivieren | / \ \--------------------/ Akteur: Benutzer Ablauf: Der Benutzer aktiviert eine spezielle der auswählbaren Aufgaben. Falls eine andere Aufgaben aktiv war, wird diese zuerst deaktiviert. Vorbedingung: Der Benutzer waehlt eine Aufgabe, die noch ueber eine Restzeit verfuegt. Es gibt einen gueltigen Zykluszaehler. Nachbedingung: Genau eine Aufgabe ist aktiv. Ausnahme: 1. Der Benutzer waehlt eine Aufgabe, deren Zeit bereits abgelaufen ist. ==> Fehlermeldung an den Benutzer 2. Es ist kein gueltiger Zyklenwert vorhanden. ==> Fehlermeldung an den Benutzer Inv.: Der Benutzer arbeitet tatsaechlich an der Aufgabe. 4.4 Aufgabe loeschen o /--------------------\ /|\ _______| Aufgabe loeschen |__________________ / \ \--------------------/ \ | << uses >> | << uses >> \|/ \|/ /----------------------\ /--------------------\ | Aufgabe deaktivieren | | Aufgabe aktivieren | \----------------------/ \--------------------/ Akteur: Benutzer Ablauf: Der aktuelle Job wird deaktiviert. Der Benutzer waehlt den Job, der geloescht werden soll. Der Job wird aus der Aufgabenliste entfernt. Der aktuelle Job wird aktiviert. War der aktuelle Job der zu loeschende, so wird kein Job aktiviert. Vorbedingung: Mindestens eine Aufgabe ist vorhanden. Nachbedingung: Die ausgewaehlte Aufgabe ist geloescht. 4.5 Aufgabe deaktivieren o /--------------------\ /|\ _______| Aufgabe deaktivieren | / \ \--------------------/ Akteur: Benutzer Ablauf: Der Benutzer deaktiviert die aktuelle Aufgabe. Vorbedingung: Der Benutzer waehlt die Aufgabe, die zur Zeit aktiv ist, oder er betaetigt einen gesonderten Schalter STOP, der sich stets auf die aktuelle Aufgabe bezieht. Nachbedingung: Keine Aufgabe ist aktiv. Inv.: Der Benutzer hoert tatsaechlich auf zu arbeiten. Ausnahme: Der Benutzer waehlt eine Aufgabe, die nicht aktiv ist. ==> Fehlermeldung an den Benutzer 4.6 Uhr Update - /---------------------------------------\ / \ ___________| Aufgabenzeit dekrementieren | \ / | \---------------------------------------/ - | /|\ | | | << extends >> | | /---------------------------------------\ | | | Aufgabenzeit auf 0 | | | \---------------------------------------/ | | | << uses >> | | \|/ | | /---------------------------------------\ | | | Aufgabe deaktivieren | | | \---------------------------------------/ | | | | /---------------------------------------\ | \____________| Bei Tagesgrenze Zyklus dekrementieren | | \---------------------------------------/ | /|\ | | << extends >> | /---------------------------------------\ | | Zyklusgrenze ueberschritten | | \---------------------------------------/ | | << uses >> | \|/ | /---------------------------------------\ | | Initialisierung der Aufgabenwerte | | \---------------------------------------/ \_________________________________ \ | \|/ /---------------------------------------\ | Dringlichkeitswert testen | \---------------------------------------/ | << extends>> \|/ /---------------------------------------\ | Dringlichkeitswert unterschritten? | \---------------------------------------/ Akteur: Uhr Ablauf: Alle Aufgaben werden ueberprueft, ob sie aktiv sind. Bei aktiver Aufgabe: die verbleibende Zeit wird dekrementiert. Ist die Zeit einer Aufgabe abgelaufen, so wird sie deaktiviert. Bei deaktivert Aufgabe: Unterschreitet der verbleibende Zeitwert den Dringlichkeitswert, wird ein Signalton ausgegeben. Liegt ein Tagewechsel vor, so wird der Zyklenzaehler dekrementiert. Befindet sich der Zyklenzaehler bei 0, so werden alle Zeitwerte der Aufgaben reinitialisiert. Vorbedingung: Ein gueltiger Zyklenwert wurde eingegeben. Es existiert mindestens eine Aufgabe. 4.7 Zyklus editieren o /--------------------\ /|\ ____| Zyklus editieren |________________ / \ \--------------------/ \ | << uses >> | << uses >> \|/ \|/ /----------------------\ /-----------------------------------\ | Aufgabe deaktivieren | | Initialisierung der Aufgabenwerte | \----------------------/ \-----------------------------------/ Akteur: Benutzer Ablauf: Der aktuelle Job wird deaktiviert. Der Benutzer gibt die neuen Angaben fuer den Zyklus ein. Alle Zeitwerte der vorhandenen Aufgaben werden initialisiert. Vorbedingung: -- Nachbedingung: Es existiert ein gueltiger Zeitwert. Alle Aufgaben haben gueltige Zeitrestangaben. Ausnahme: Die Zyklusangabe ist inkorrekt. ==> Fehlermeldung an den Benutzer 4.8 Dringlichkeitswert eingeben o /-----------------------------\ /|\ ____| Dringlichkeitswert eingeben |________________ / \ \-----------------------------/ \ | << uses >> | << uses >> \|/ \|/ /----------------------\ /--------------------\ | Aufgabe deaktivieren | | Aufgabe aktivieren | \----------------------/ \--------------------/ Akteur: Benutzer Ablauf: Der aktuellle Job wird deaktiviert. Der Benutzer gibt die neuen Angaben fuer den Dringlichkeitswert ein. Alle Zeitwerte der vorhandenen Aufgaben werden initialisiert. Der aktuelle Job wird aktiviert. (Der veraenderte Job muss nicht automatisch zum aktuellen Job werden.) Vorbedingung: -- Nachbedingung: Es existiert ein gueltiger Zeitwert. Alle Aufgaben haben gueltige Zeitrestangaben. Ausnahme: Die Zyklusangabe ist inkorrekt. ==> Fehlermeldung an den Benutzer 5. Produktdaten Das Produkt erwartet eine Einteilung der Zeit in Zyklen. Die Grundeinheit fuer einen Zyklus betraegt hierbei einen Tag. Ein Zyklus kann Werte annehmen zwischen 1 (ein Tag) bis 366 (ein Jahr). Alle Eingaben der Aufgaben basieren auf den Werten Zyklus, Tag, Stunde, Minute. Die Laenge eines Tages soll hierbei tatsaechliche 24 Stunden betragen und nicht Arbeitsstunden (z. B. 8 Stunden). 6. Leistungen (Spezielle Leistungen) -- 7. Benutzeroberflaeche 7.1 Alle Ein-/Ausgaben sollten ueber Fenster erfolgen und ueber die Mausschnittstelle angewaehlt werden koennen. 7.2 Alle Aufgaben sollten staendig vollstaendig (Name, verbleibende Zeit) auf dem Bildschirm visualiert werden. 7.3 Die aktuelle Aufgabe sollte dabei nach Moeglichkeit graphisch hervorgehoben werden, z. B. durch Verwendung einer anderern Farbe, Schriftgroesse etc. 8. Qualitaetszeichen 8.1 Fehlerfreiheit Eine Standardfehlerfreiheit ist erwuenscht: +- 8.2 Erweiterbarkeit Erweiterbarkeit kann nicht ausgeschlossen werden (z. B. Stundennachweise ausdrucken fuer den Arbeitgeber etc): ++ 8.3 Wartbarkeit Eine Standardwartbarkeit ist erwuenscht: +- 9. Testszenarien -- 10. Entwicklungsumgebung Das Programm soll mit Hilfe einer JAVA-Programmierumgebung entworfen werden. Fertige Programme sollten auf jedem JAVA-Interpreter ablauffaehig sein. 11. Ergaenzung (Verschiedenes) -- Klassendefinition: ================== zu definierende Klassen: 1.) time _________________________________________________________________________________ | | | time | |_______________________________________________________________________________| | | | int day { 0 <= day <= 31 } | | int hour { 0 <= hour <= 23 } | | int minute { 0 <= minute <= 59 } | | int second { 0 <= second <= 59 } | |_______________________________________________________________________________| | | | Constructor(pDay,pHour,pMinute,pSecond) { benutzt SetTime ) | | SetTime(pDay,pHour,pMinute,pSecond) { testet auf Bereich } | | SubTime(pTime1,pTime2) { bildet Differenz } | | IsLowerThan(pTime1,pTime2) { Vergleicht auf Kleiner } | | { benutzt SubTime } | |_______________________________________________________________________________| 2.) job _________________________________________________________________________________ | | | job | |_______________________________________________________________________________| | | | *job nextjob { Zeiger auf naechsten Job in jobliste } | | string[256] name { Name des Jobs muss vorhanden sein } | | time inittime { Initialzeit pro Zykles } | | time runtime { runtergezaehlte Zeit } | |_______________________________________________________________________________| | | | Constructor(pName,pInittime) { fuegt Job in Liste hinzu } | | Deconstructor() { loescht Job aus Liste } | | Resetjobtime() { setzt Job runtime auf inittime } | | Subjobtime() { ziehe Zeit von runtime ab } | | Drawjob() { Parameter GUI-abhaengig } | |_______________________________________________________________________________| Desweiteren gibt es noch folgende globale Variablen: time acttime { aktuell ermittelte Echtzeit } time oldtime { die jeweils davor ermittelte Zeit } { oldtime = acttime } time zyklus { Laenge des Zyklus } time starttime{ Zyklusanfangszeit } { starttime = acttime } time subtime { die Differenz aus alter Zeit und akueller Zeit } *job anchor { zeigt auf den ersten Job. } { anchor = NIL } *job active { Zeiger auf aktuellen aktiven Job } { active = NIL } *job run { Zeiger fuer die Schleifenbehandlung der Liste } action useraction { messagestruktur des Systems } boolean delay { haelt fest, ob es zu einer Verzoegerung im } { Programm kam. Dient genauerer Berechnung der } { tatsaechlich geleisteten Arbeitszeit } { delay = FALSE } Beispielhafte Pseudocode-Implementierung: ========================================= Die Applikation selbst enthaelt folgende Hauptstruktur: REPEAT SLEEP(x ms); { multitaskingfreundliche Kontrollabgabe im genau zu definierenden Intervall (Millisekunden) } IF signal(realtimeclock) THEN { wenn die Uhr ein Updatesignal liefert } BEGIN acttime:=systemclock(); { Hole die Zeit durch Systemaufruf } IF (active <> NIL) THEN { Wenn ein job aktiviert wurde, dann } BEGIN subtime:=acttime - oldtime; { Differenz bilden ==> vergangene Zeit } subjobtime(subtime); { ziehe Differenzzeit von runtime ab } END; run:=anchor; subtime:=zyklus - acttime - starttime { Zyklenrestzeit } WHILE (run <> NIL) DO BEGIN IF (IsLessThan(subtime,run^.runtime) THEN alert(); { gib Warnung aus } run:=run^.nextjob; { auf naechsten Job gehen } END; drawobjects(); { Male jobs etc neu } END; { IF } IF signal(action) THEN { Hat der Benutzer eine Aktion ausgeloest ? ) BEGIN useraction:=getaction(); { hole genaue Aktionsbestimmung } CASE action OF deletebutton : deletejob; { job loeschen } addbutton : addjob; { job hinzufuegen } stopbutton : stopjob; { deaktiviere aktuellen job } editbutton : editjob; { veraendere job } END; END; IF delay THEN { kam es zu einer laengeren Verzoegerung im } BEGIN { Programm, so muss die Uhrzeit neu gelesen } oldtime:=systemclock(); { werden. Ansonsten wird mit dem aktuellen } delay:=FALSE { Wert weitergearbeitet. } END ELSE oldtime:=acttime; UNTIL useraction = exitprogram; Falls das zugrundeliegende System es erlaubt, so kann selbstverstaendlich anstelle einer definierten Wartezeit auch auf 2 Ereignisse (Uhr, Benutzer) gleichzeitig gewartet werden. Durch die Trennung der Signale in eine sequentielle Singlethreadstruktur wird gewaehrleistet, dass der Zugriff auf die globalen Variablen kontrolliert erfolgt. Ausserdem erhaelt so der Benutzer jeweils immer bei allen Aktionen ohne unnoetigen Programmieraufwand eine korrekte Anzeige der Daten (Restzeit etc). Mit freundlichen Gruessen Henning Lohmeyer, Holger Picker