Wie wird man Praktikant bei Knuddels?

Wie wird man Praktikant bei Knuddels?
Das ist eine gute Frage. Ehrlichgesagt kam das selbst für mich etwas überraschend weil es so schnell ging.
Angefangen hat eigentlich alles in einer Hochschulgruppe namens Pioniergarage an meiner Hochschule.
Damals hab ich einen Vortrag zu einem meiner Projekte gehalten.

IMAG5126

Und jetzt rate mal wer da saß und zugehört hat?
Holger!
Naja anscheinend hat ihm wenigstens ein bisschen gefallen was ich da erzählt habe 🙂
Mein Projekt ging nämlich auch in Richtung Chatten und Community.
Genau darüber haben wir uns dann auch unterhalten und kamen irgendwann auf ein Praktikum zu sprechen.

Leider hatte ich zu der Zeit noch kein Bedarf für ein Praktikum…
Also haben sich die Wogen erst ein Mal geglättet.
Bis… Ja bis vor ca 3 Monaten. Ich dachte mir: „Marvin, warum machst du dein Praktikum nicht im nächsten Semester?“
Tja warum eigentlich nicht? Am nächsten Tag hab ich Holger einfach nochmal angeschrieben.

Und jetzt bin ich hier 🙂
Ich finde es übrigens richtig toll, dass ihr meinen Blog lest.
Wenn ihr Fragen, Kritik oder Vorschläge habt schreibt mir bitte.
Ich würde mich freuen.

Liebe Grüße, MarvinDerPraktikant.

[5] Neue User wissen jetzt sofort die aktuelle Aufgabe

Hey there.
Ich will dich etwas fragen. Darf ich?
Ok.
Kennst du diesen Moment aus der Schule: Alle sind am rechnen, nur du weißt wieder mal die Aufgabe nicht?
Du frägst deinen Nachbarn um Rat, aber der zeigt nur stumm auf eine Seite im Buch.
Naja als du dann endlich rausgefunden hast was du machen sollst sind die anderen schon fertig.

FreeGreatPicture.com-5863-folding-book

Bis jetzt funktioniert der KopfTrainer leider auch so.
Wenn ein User den Channel betritt weiß er nicht sofort welche Aufgabe gerade zu lösen ist.
Das will ich verhindern.

Ich hab mir dazu ein Paar Gedanken gemacht.
Erst wusste ich nicht wo ich die aktuelle Frage herbekommen soll.
Aber dann ist mir eingefallen, dass die Frage ja immer in der globalen Variable equation gespeichert ist.
Das heißt man kann sie jedem User der den Channel betritt einfach so schreiben.
Sofern gerade eine Aufgabe läuft natürlich.

var App = {};
App.onUserJoined = function(user)
{
user.sendPrivateMessage('Hey, cool dass du da bist!');
if (equationRunning == false)
{
createNewMathEquation();
}
else
{
user.sendPrivateMessage('Hier hast du die aktuelle Aufgabe: Was ergibt ' + equation + ' ?');
}
};

Cool! Das funktioniert!
Glaub mir, ich war echt froh als das geklappt hat. Meiner Meinung nach kann die App bisher schon recht viel.
Ich bin aber voll eurer Meinung, was den Highscore angeht.
Ein Highscore muss auf jeden Fall noch dazu.
Im Moment weiß ich aber gar nicht wie man Dinge überhaupt speichern kann.
Wenn ich rausfinde wie das geht schreibe ich nochmal, ok?

Liebe Grüße, MarvinDerPraktikant.

[4] Die App erkennt jetzt richtige Antworten

Hey there.
Schon cool was die KopfTrainer App bisher alles kann oder? Sie kann User begrüßen und verabschieden. Außerdem kann sie schon alle 15 Sekunden eine Matheaufgabe ausgeben und damit die neue Runde einläuten.

laptop

Jetzt gehts ans Eingemachte.
Ich will mich jetzt der Überprüfung von Antworten widmen.
Den ersten Schritt dazu habe ich ja schon im zweiten Tutorial [Link zum zweiten Tutorial] gemacht.
Dort hat die App jedem User eine private Nachricht geschrieben, wenn er etwas in den Channel gepostet hat.
Und genau an dem Punkt setze ich jetzt an.
Los gehts:

Weißt du, zu aller erst hab ich mich gefragt wie man überhaupt den Text einer Nachricht aus dem Message Objekt bekommen kann.
Aber auch dafür hat die API eine Lösung.

var App = {};
App.onPublicMessage = function(message)
{
// Unser alter Code.
message.getAuthor().sendPrivateMessage('Erwischt! Du hast gerade eine Nachricht in den Channel    geschrieben stimmts?');
// Hier holen wir aus dem Message Objekt den Text.
var messageText = message.getText();
};

Jetzt da ich den Nachrichtentext habe, kann ich überprüfen ob er mit der Lösung zur aktuellen Aufgabe übereinstimmt.
Die Lösung zur aktuellen Aufgabe ist ja zum Glück immer in der globalen Variable solution gespeichert.

var App = {};
App.onPublicMessage = function(message)
{
// Unser alter Code.
message.getAuthor().sendPrivateMessage('Erwischt! Du hast gerade eine Nachricht in den Channel   geschrieben stimmts?');
// Hier holen wir aus dem Message Objekt den Text.
var messageText = message.getText();
// Und jetzt überprüfen wir den Text auf die richtige Antwort.
if(messageText.indexOf(solution)>-1)
{
// Der User hat richtig geantwortet.
}
else
{
// Der User hat falsch geantwortet.
}
};

Ok was hier passiert habe ich am Anfang auch nicht verstanden. Mach dir keine Sorgen, es ist eigentlich ganz einfach.
Die JavaScript Funktion indexOf() gibt immer den Ort eines Strings in einem anderen String zurück.
Aber was ist blos ein String? Ein String ist im Grunde nichts anderes als Text. Und da sowohl die Nachricht im Channel, als auch die Lösung aus Text besteht kann man so nach der richtigen Lösung suchen.

Hier ein Beispiel mit dem ich es verstanden habe:

var erdbeerenSindRot = "Erdbeeren sind rot";
var sind = "sind";
var banane = "Banane";
var kommtImTextVor = erdbeerenSindRot.indexOf(sind);
var kommtNichtImTextVor = erdbeerenSindRot.indexOf(banane);

Was bedeutet das jetzt?
Da die Funktion indexOf() immer die Stelle in der ein String in einem anderen vorkommt zurückgibt, hat die Variable kommtImTextVor jetzt den Wert 10. Das Wort „sind“ beginnt an 10ter Stelle des Textes erdbeerenSindRot.
Welchen Wert hat dann die Variable kommtNichtImTextVor? Da „Banane“ nicht in erdbeerenSindRot vorkommt hat kommtNichtImTextVor den Wert -1.

Ihr könnt euch also merken: Kommt ein String nicht in einem anderen vor, gibt indexOf() den Wert -1 zurück.

Puh! Das war gar nicht so leicht.
Aber jetzt da ich weiß ob ein User die richtige Antwort in den Channel geschrieben hat kann ich ihm gratulieren. Wie man private und öffentliche Nachrichten verschickt haben wir ja auch schon gesehen.

var App = {};
App.onPublicMessage = function(message)
{
// Unser alter Code.
message.getAuthor().sendPrivateMessage('Erwischt! Du hast gerade eine Nachricht in den Channel   geschrieben stimmts?');
// Hier holen wir aus dem Message Objekt den Text.
var messageText = message.getText();
// Und jetzt überprüfen wir den Text auf die richtige Antwort.
if(messageText.indexOf(solution)>-1)
{
// Der User hat richtig geantwortet.
message.getAuthor().sendPrivateMessage('Super gemacht. Du hast die Aufgabe geloest!');
appBot.sendPublicMessage('_______ ' + message.getAuthor() + ' hat die Aufgabe geloest _______');
}
else
{
// Der User hat falsch geantwortet.
}
};

Cool oder?
Also ich finde die App bisher super. Und was meint ihr dazu?
Irgendwie fehlt mir aber noch etwas.
Wie wäre es wenn neue User mit der aktuellen Frage begrüßt werden?

Darum geht es dann im nächten Blog Eintrag.
Bis dann 🙂

Liebe Grüße, MarvinDerPraktikant.

[3] Die erste Matheaufgabe

Hey there.
Da bist du ja wieder. Ich freue mich schon auf den heutigen Blog.
Denn heute geht es endlich um die eigentliche Matheaufgabe.

desk

Ich hab dir ja erzählt, dass ich erst ein Mal alle 15 Sekunden eine neue Aufgabe ausgeben will, oder?
Genau dazu hab ich mich mal schlau gemacht.
Was ich herausgefunden habe ist folgendes:

Es gibt in JavaScript eine Funktion namens setTimeout(function(), time), die als Parameter zum einen eine Funktion erwartet. Die Funktion die später ausgeführt wird. Und zum anderen die Zeit nach der die Funktion ausgeführt wird. Die Zeit selbst übergibt man in Millisekunden.

var appBot = KnuddelsServer.getDefaultBotUser();
var solution;
var equation;
var equationRunning = false;

function createNewMathEquation()
{
var parts = Math.floor((Math.random() * 10) + 1);
var equationNew;
var solutionNew;

var firstNumber = Math.floor((Math.random() * 10) + 1);
equationNew = firstNumber;
solutionNew = firstNumber;

for(var i = 0; i < parts; i++)
{
var operatorNumber = Math.floor((Math.random() * 2) + 1);
var operator;
if(operatorNumber==1)
{
operator = ' + ';
var number = Math.floor((Math.random() * 10) + 1);
equationNew = equationNew + operator + number;
solutionNew = solutionNew + number;
}
if(operatorNumber==2)
{
operator = ' – ';
var number = Math.floor((Math.random() * 10) + 1);
equationNew = equationNew + operator + number;
solutionNew = solutionNew – number;
}
}

equationRunning = true;
equation = equationNew;
solution = solutionNew;

appBot.sendPublicMessage('____________________ DIESE RUNDE IST LEIDER VORBEI _______________________');
appBot.sendPublicMessage('Die neue Aufgabe lautet: Was ergibt ' + equation);

setTimeout(function startNewRound(){createNewMathEquation();}, 15000);

return equationNew;
}

Wie du siehst hab ich die Funktion setTimeout(function(), time) gleich verwendet um createNewMathEquation() immer wieder aufzurufen.
Du hast ganz Recht. Oben steht ja auch noch etwas Neues.

var appBot = KnuddelsServer.getDefaultBotUser();

Macht nichts anderes als den mit dem Channel verknüpften Bot zu holen und ihn in der Variable appBot abzulegen.
Ich hab nämlich rausgefunden, dass man um öffentliche Nachrichten zu verschicken, den Bot der App braucht. Weil der ja quasi in den Channel schreibt.

Das wars auch schon fast:
Wenn die Funktion createNewMathEquation() ein Mal läuft, ruft sie sich immer wieder von selbst auf.
Aber was wenn sie noch nicht läuft? Naja, dann muss man sie ein mal selbst aufrufen…
Ich hab mir folgendes gedacht:

App.onUserJoined = function(user)
{
user.sendPrivateMessage(‚Hey, cool dass du da bist!‘);
if (equationRunning == false)
{
createNewMathEquation();
}
else
{

}
};

Was passiert hier?
Wenn ein User den Channel betritt wird überprüft ob gerade eine Mathegleichung läuft oder nicht.
Falls nein: Starte ich eine.
Falls ja: Tue ich nichts.

Tada!
Blos schade, dass die Antworten auf aktuelle Mathefragen noch nicht geprüft werden…
Aber genau darum geht es ja im nächsten Blogeintrag.
Bis gleich dann 🙂

Liebe Grüße, MarvinDerPraktikant.

[2] Was muss unbedingt in die KopfTrainer App?

Hey there.
Danke erst mal für euer super Feedback.
Wie immer gilt: Wenn ihr zu dieser Blogserie beitragen wollt, Tipps oder Vorschläge habt. Schreibt mir einfach 🙂

Also lasst uns loslegen.
Ich denke es wird Zeit dass die App Form annimmt. Dazu hab ich mir mal ein Paar Gedanken gemacht.

keyboard2

Ich hab euch ja im letzten Blogeintrag über die verschiedenen Funktionen einer App berichtet stimmts?
Jetzt gehts darum zu entscheiden welche davon für die KopfTrainer App sinnvoll sind.

Also was muss unbedingt in die App?
Neue User im Channel zu begrüßen klappt ja zum Glück schon. Ein Punkt weniger auf der Liste 😀
Jetzt fehlen noch die Matheaufgaben, deren Überprüfung und die Verabschiedung der User.
Hmm. Was könnte man sinnvollerweiße zuerst machen?

Die Verabschiedung der User:

App.onUserLeft = function(user)
{
user.sendPrivateMessage('Du gehst schon? Schade... Hoffentlich bis bald.');
};

Cool! Sobald jetzt ein User meinen Channel verlässt wird er vom Appbot verabschiedet.

Wie könnte man Antworten zu den Matheaufgaben überprüfen?
Einige von euch meinten ja, dass man Antworten einfach so in den Channel schreiben sollte. Dann sieht sie auch jeder. Außerdem würde das den Spannungsfaktor steigern.
Ich fand die Idee super und hab mich gleich an die Umsetzung gemacht.

Um öffentliche Nachrichten im Channel zu empfangen, das weiß ich jetzt, braucht man die Funktion onPublicMessage(message), die die neue Nachricht übergibt. Ich glaube es reicht mir erst mal nur dem User der gerade in den Channel geschrieben hat eine Nachricht zu schicken. Aber darauf kann man ja später aufbauen 🙂

Das ganze könnte zum Beispiel so aussehen:

App.onPublicMessage = function(message)
{
message.getAuthor().sendPrivateMessage('Erwischt! Du hast gerade eine Nachricht in den Channel geschrieben stimmts?');
};

Was fehlt jetzt noch?
Natürlich die Matheaufgabe selbst. 😀 Ohne die kann auch nichts beantwortet werden.
Ich glaube ich hab schon eine Idee.
Wie wäre es wenn die App alle 15 Sekunden eine Matheaufgabe ausgibt und damit eine neue Runde startet?
Hmm… Das klingt schwer.
Ich überlege mir jetzt Mal wie man das umsetzen könnte.
Wenn du wissen willst ob ich das Problem lösen kann schau doch im nächsten Blog vorbei.

Wir sehen uns dort oder?
Bis gleich.

Liebe Grüße, MarvinDerPraktikant.

[1] Wie ist eine App eigentlich aufgebaut?

Hey there.
Cool dass du da bist. Weisst du schon, was ich vor habe? Nein? Dann lies doch mal hier.
Ich hab jetzt begonnen mir etwas über die User Apps durchzulesen.

So hab mich mir das am Anfang vorgestellt:

appScaled

Das ganze User Apps System ist schon ganz schön umfangreich, aber ich glaube, ich habe den Kniff jetzt raus. Um die Apps besser zu verstehen habe ich mir folgendes klar gemacht:

var App = {};
App.onUserJoined = function(user)
{
};

Eine App besteht aus mehreren Funktionen die man implementieren kann:
Implementieren? Das bedeutet nichts anderes als einbauen.
Außer den drei Funktionen hier gibt es noch einige andere, die ich in der API Dokumentation gesehen habe.

Doch: Was bringen mir die Funktionen jetzt?
Ich hab das so verstanden: Anscheinend hat jede App die oben erwähnten Funktionen und immer wenn etwas in einem Channel passiert, dann werden sie aufgerufen. Wenn zum Beispiel ein User den Channel betritt oder verlässt, wenn eine Nachricht geschrieben wird oder die Würfel gerollt werden. Immer dann wird eine der Funktionen von oben aufgerufen und ich kann darauf reagieren.

Zum Beispiel merke ich mit der Funktion onUserJoined(user) immer, wenn gerade ein User den Channel betritt.

Cool, dann kann ich ja alle Leute begrüßen, die bei mir in den Channel kommen!
Nach ein paar Versuchen hatte ichs dann raus. So geht das:

var App = {};
App.onUserJoined = function(user)
{
user.sendPrivateMessage('Hey, cool dass du da bist!');
};


Wie geht’s jetzt weiter?

Macht schon irgendwie Spaß das Ganze! Genau deshalb mache ich jetzt auch direkt weiter und lese mir ein bisschen mehr zu den Apps durch. Komm doch mit?

Also bis gleich 🙂
Liebe Grüße, MarvinDerPraktikant.

[0] Was ist eine Knuddels App?

Apps.
Was ist das eigentlich? Was versteht ihr unter einer App? 99% von euch stellen sich jetzt ein Handy vor.
Was wenn ich euch erzähle, dass es auch Apps gibt die nicht auf dem Handy laufen?
„Und wo sonst?“
Eine durchaus berechtigte Frage.

knuddels

Was haben wir früher alle gern getan?
Center Shocks gegessen und Pokémon gespielt. Klar. Vielleicht frage ich noch mal. Jetzt etwas direkter. Was haben wir am Computer gern getan?
Gechattet. Ja richtig! Gechattet. Kennt ihr noch ICQ, MSN und was es sonst noch alles gab?
Heute gibt es Knuddels. Viele von uns Chatten immer noch. Und das machen sie genau dort.

Zu so einem Chat gehören natürlich auch Chaträume.
Ihr wisst schon. Diese viereckigen Boxen. Alle mit verschiedenen Hintergründen. Ach ja fast hätte ich es vergessen. Man chattet darin mit vielen anderen Menschen, hat seinen Spaß und lernt jede Menge interessanter Charaktere kennen. In so einem Chatraum oder Channel kann auch eine App „laufen“. Natürlich läuft sie nicht wirklich. Ehrlichgesagt bewegt sie sich gar nicht mehr wenn sie erst mal auf einem Channel läuft. Eigentlich bedeutet das, dass sie dort installiert ist.

So eine App ist in der Lage ganz verschiedene Dinge zu tun.
Wenn ich dir jetzt erzähle, dass sie sich Dinge merken kann… Glaubst du mir dann? Und was wenn ich dir sage, dass sie im Channel ein Spiel leiten könnte.

Ein Spiel bei dem du mal so richtig zeigen kannst wie fit du noch bist. Die App könnte sich zum Beispiel eine kleine Matheaufgabe ausdenken, die sie dann allen die sich gerade im Channel befinden stellt.
Ab diesem Moment passt die App ganz genau auf was im Channel geschrieben wird. Wenn einer der Chatter schnell genug auf die richtige Antwort kommt und diese in den Channel schreibt belohnt sie ihn mit ein wenig Aufmerksamkeit.
Wollen wir nicht alle ein wenig Aufmerksamkeit für besonders gute Leistungen? Schon oder? Naja und deswegen schreibt die App in den Channel dass Chatter XYZ die Aufgabe gelöst hat.
Jetzt kann er sich noch selbst auf die Schulter klopfen und danach direkt die nächste Aufgabe beantworten.

Was ich gerade beschrieben habe ist nur eines von vielen Beispielen für eine solche App.
Wenn ihr euch mal auf Knuddels umseht werdet ihr noch eine Menge anderer Arten von Apps finden. Da gibt es zum Beispiel das SnakeGame (Channel: SnakeGame). Wobei wir wieder zurück in unserer Kindheit wären :D. Aber auch ganze Rollenspiele. Untergebracht in einem Chatraum. Ja du hast richtig gehört. Ein Rollenspiel (Channel: Knuddelonia). Glaubst du nicht? Na dann schau selbst nach auf http://www.knuddels.de

Wir wollen uns jetzt erst einmal damit begnügen die oben beschriebene App zu bauen.
Nicht weil ich keine Lust hätte Snake oder ein Rollenspiel zu programmieren. Nein. Im Moment würde ich das einfach nicht schaffen. Ich geh lieber erst Mal langsam an die ganze Sache ran. Zusammen mit euch!
Ich bin mir sicher, dass wir später noch auf ein Paar coole Ideen kommen werden.
Los geht’s dann in meinem nächsten Blog Eintrag.
Seid gespannt und bleibt dabei.
Liebe Grüße, MarvinDerPraktikant.

[10] Den permanenten Highscore ausgeben

Hey there.
Wie stellst du dir einen Highscore vor?
Ich persönlich denke dabei an eine Art Tabelle in der Spieler je nach Score aufgelistet werden.
Hmm. Den Highscore der User habe ich ja jetzt gespeichert. Nur wie gebe ich ihn wieder aus? Vor allem: wie gebe ich die User sortiert nach der Höhe ihres Highscores wieder aus?

Das Ausgeben des Highscores,
hat sich für mich am Anfang sehr schwer gestaltet. Im ernst. Für mich war das bis jetzt das schwerste Thema.
Ich habe erst versucht für jeden User im Channel den Highscore einzeln auszulesen und den dann in einem eigenen Objekt (Vergleich Blog 6: Telefonbuch) abzulegen.
Natürlich waren die Einträge in meinem Objekt (Telefonbuch) dann noch nicht sortiert.
Also habe ich versucht die Einträge im Objekt mit mehreren for Schleifen zu sortieren… Das war nicht optimal.
Dann habe ich alle Einträge des Objekts (Telefonbuch) in ein Array geladen und dieses mit dem sort Befehl sortiert.
Das war natürlich auch nicht die beste Lösung.
Naja. Du merkst schon, ich bin erst Mal richtig auf die Nase gefallen.

Aber dann hab ich wieder in die API geschaut:
Es gibt in der API eine Klasse die sich UserPersistenceNumbers nennt.
Was ist das?
Die Klasse UserPersistenceNumbers kann helfen gespeicherte Daten aus allen UserPersistence Objekten für alle User deiner App zu „holen“. Du erinnerst dich ja noch, dass jeder User in deiner App ein eigenes PersistenceObjekt hat, oder?

persistence_app_users8_channelScaled
Falls nein: Lies doch nochmal meinen letzten Blogeintrag.

Jetzt stell dir vor in deiner App gibt es mehr als zwei User. Vielleicht schon acht?
Alle User haben ihr eigenes UserPersistence Objekt. Und in jedem Objekt ist der Highscore für den damit verbundenen User gespeichert. Du erinnerst dich, dass der Highscore unter einem Key gespeichert ist?

const PERM_SCORE = "perm_score";

 

memory_key_perm_score

Mit dem UserPersistenceNumbers Objekt und dem Key kann man jetzt all diese Daten auf einmal auslesen und sogar sortieren.
Das macht man so:
userPersistenceNumbers_with_key
Diese Daten sind dann in einem Array gespeichert.

Wie programmiert man das jetzt?

// Mit der Funktion getSortedEntries gibt das UserPersistenceNumbers Objekt (Die Krake) alle Einträge unter dem Key PERM_SCORE = "perm_score" (siehe oben) sortiert zurück.
function printPermScore()
{
var topUser = UserPersistenceNumbers.getSortedEntries(PERM_SCORE, {
ascending: false,
count: 10,
});
for(var i = 0; i<topUser.length; i++){
publicMessage(boldText('['+(i+1)+': ' + topUser[i].getUser() + " Punkte: " + topUser[i].getValue()+']'));
}
}

[1] Ich hole mir erst mit Hilfe des UserPersistenceNumber Objektes (Die Krake) alle Einträge aller User unter dem Key „perm_score“.
[2] Diese werden dann in einem Array namens topUser abgespeichert.
[3] Zum Schluss iteriere ich (Das heißt nichts anderes als durchlaufen) noch über dieses Array und gebe mit der Funktion publicMessage(text), die du ja schon kennst, den Highscore aus.

Das war es dann auch schon fast:
Die Funktion printPermScore() musste ich dann nur noch zum richtigen Zeitpunkt aufrufen.
Ich habe mich dafür entschieden sie vor jeder Runde ein Mal aufzurufen:

function createNewMathEquation()
{
printPermScore();// Hier kommt eigentlich noch der restliche Code der die neue Aufgabe generiert. Aber damit verschone ich dich jetzt.
// Wer den nochmal sehen will kann in meinem dritten Blogeintrag nachlesen.
}

Jetzt mal eine Frage an euch:
Wie soll es mit der KopfTrainer App weitergehen?
Sollte ich sie noch ein wenig aufhübschen? Oder lieber einen neuen Spielmodus oder sogar ein ganz anderes Denkspiel implementieren?
Schreibt mir doch eure Ideen.

Liebe Grüße, MarvinDerPraktikant.

[9] Der permanente Highscore

Hey there.
Wow. Das ist jetzt schon der neunte Blogeintrag zur KopfTrainer App. Wie schnell die Zeit vergeht…
Die App kann bisher temporär Dinge speichern.
Das heißt leider dass Dinge eigentlich nicht wirklich gespeichert werden…
Dazu müsste man einen persistenten Highscore programmieren.
beachMountains
Wie programmiert man einen persistenten Highscore?
Persistent? Was bedeutet das eigentlich?
Persistent bedeutet eigentlich nichts anderes als dauerhaft. Dinge werden dauerhaft in deiner App gespeichert und sind von einem Neustart oder Absturz der App nicht mehr betroffen.

Als ich mir das zum ersten Mal in der API angesehen habe war ich überwältigt…
Ich dachte mir: „Mensch ist das viel“
Aber eigentlich war es gar nicht so schwer. So hab ich dann verstanden wie das UserPersistence Objekt funktioniert:

userScaled
Das ist ein User. Zum Beispiel du, oder jede andere Person die du auf Knuddels kennst.


channelScaled
Hier haben wir einen Channel. Darin chattest du immer.


appScaled
Sag hallo zu deiner App. Die sieht nämlich so aus.


memory
Und last but not least: Das Persistence Objekt. Wozu man das braucht erfährst du gleich.


user_channelScaled

Das bist du. Du bist gerade in deinem eigenen Channel und hast dort noch keine App installiert.


app_user_channelScaled

Das war dir natürlich nicht genug. Also hast du dir eine erste App programmiert. Vielleicht hast du auch einfach den KopfTrainer oder die HeyThere App ausprobiert?


app2_user_channelScaled

Du musst wissen, dass du in einem Channel mehr als eine App installieren kannst. Die können auch gleichzeitig laufen.
In deinem Channel hast du jetzt zwei Apps. Die Blaue und die Gelbe.


persistence_app2_user_channelScaled
Jetzt wird’s spannend. Du als User hast für jede App genau ein Persistence Objekt. Das heißt du kannst in der gelben und der blauen App zwei Dinge unter dem gleichen Key (Schlüssel) speichern.
Zum Beispiel könntest du in der blauen App unter dem Key „Name“ : Johannes speichern. Und in der gelben etwas ganz anderes. Zum Beispiel „Name“ : Lukas.
Was ein Key ist haben wir ja schon in meinem 6. Blog Eintrag gelernt. Falls du dich nicht mehr genau daran erinnerst, schau doch kurz hier nach.


persistence_app2_user2_channelScaled

Was ist jetzt passiert?
Für mich war das hier der schwierigste Part.
Wenn nämlich einer deiner Freunde, oder überhaupt ein anderer User, in deinen Channel kommt. Naja dann hat der neue User auch in jeder App sein eigenes Persistence Objekt. Wie du siehst zeigen die roten Pfeile des neuen Users beide zu ganz anderen Persistence Objekten.

Wie programmiert man das jetzt?
Als ich das alles verstanden hatte war das Programmieren an sich gar nicht mehr so schwer.
Zuerst wollte ich eine Funktion schreiben, die gleichzeitig den temporäre und den globalen also persistenten Highscore speichern kann:

function addScore(user, amount)
{
addTempScore(user, amount);
addPermScore(user, amount);
}

An der Funktion addTempScore(user, amount) hat sich nichts geändert. Anstatt sie direkt aufzurufen, rufe ich jetzt einfach zuerst die Funktion addScore(user, amount) auf. AddScore(user, amount) übernimmt quasi alles, was mit dem Hinzufügen des Highscores eines Users zutun hat.

Wie sieht die Funktion addPermScore(user, amount) aus?
Hier passiert eigentlich die ganze Magie. Hier speichere ich Daten in der UserPersistence.

function addPermScore(user, amount)
{
var persistence = user.getPersistence();
persistence.addNumber(PERM_SCORE, amount);
}

[1] Um Daten in einem UserPersistence Objekt zu speichern (Das war die kleine Diskette von oben) muss man sich das UserPersistence Objekt erst einmal für jeden User holen. Puh, was für ein Satz 😀
Wenn du das Objekt nicht über user.getPersistence() „holst“ kannst du darauf nicht zugreifen.
[2] In der Variable persistence ist jetzt das UserPersistence Objekt für den User gespeichert. Juhuu! 🙂 Jetzt kann ich endlich Dinge darin abspeichern.
[3] Das Abspeichern funktionert eigentlich wieder wie mit dem temporären Highscore. Wir speichern unter einem bestimmten Key eine Zahl. Hier den Highscore des Users.

Wieso ist der Key so komisch groß geschrieben?
Das liegt daran, dass PERM_SCORE eine Konstante ist.
Konstante? Man hat mir erklärt, dass man eine Konstante, wenn sie mal initialisiert wurde, nicht mehr ändern kann. Was sehr gut ist.
Stell dir vor irgendjemand ändert den Key für die gespeicherten Daten. Dann wären sie für immer verloren.
Wenn du den Schlüssel zu deiner Haustür verlierst kommst du ja auch nicht mehr rein stimmt’s?
Den Key habe ich genau deshalb ganz oben in der App definiert:

const PERM_SCORE = "perm_score";

Wo liegt jetzt der Unterschied zum temporären Highscore?
Das habe ich mich auch zu allererst gefragt.
Wie du vielleicht bemerkt hast, musste ich um den permanenten Highscore zu implementieren viel weniger Code schreiben als beim temporären Highscore.
Das liegt daran, dass die Knuddels API sehr viel Arbeit im Hintergrund übernimmt.
Ich musste für den permanenten Highscore nicht erst ein „Telefonbuch“ erstellen. Und dann einen „Eintrag“ schreiben. Nein. Ich konnte sofort etwas für den User hineinschreiben.
Falls du nicht mehr weißt was ich mit Telefonbuch oder Eintrag meine, schau dir doch nochmal den 6. Blogeintrag an.

Wie gibt man den permanenten Highscore wieder aus?
Gut dass du frägst.
Du hast ganz Recht. Im Moment sieht noch keiner den permanenten Highscore. Also die Rangliste die selbst dann bleibt wenn der User den Channel verlässt.
Darum möchte ich mich aber im nächsten Blog Eintrag kümmern.

Du kommst doch wieder vorbei oder?
Achja: Vergiss bitte nicht. Wenn du Fragen oder Vorschläge zur KopfTrainer App oder diesem Blog hast. Schreib mir doch einfach :).
Liebe Grüße, MarvinDerPraktikant.

[8] Wie hübscht man eine App auf?

Hey there.
Super! Die App nimmt immer mehr Form an.
Glaub mir, auf das was jetzt kommt freue ich mich schon lange. Endlich wird die App hübsch :).
Wie könnte man das anstellen?

ny
Ausnahmsweiße mal keine Kaffeetasse oder Tastatur 😀 Abwechslung muss sein.

Ich dachte mir:
warum mache ich mich nicht zuerst am Text zu schaffen? Nur wie verändert man das Aussehen des Texts im Channel?
Wie drucke ich einen Text fett? Wie stelle ich ein Wort farbig dar?
Natürlich hatte ich noch viel mehr Fragen im Kopf. Aber damit will ich dich jetzt nicht nerven.
Also was hab ich getan? Ich sags dir: Ich hab nochmal ein bisschen im Wiki für Knuddels Apps gestöbert und bin auf folgende Seite gestoßen: Typografie.
Natürlich… Der KCode. Den kann man ja überall im Knuddels Chat benutzen.
Ich hatte persönlich noch nicht viel damit zutun, deshalb verzei mir bitte wenn dir das was jetzt kommt zu langsam geht.

Text fett drucken:
Im Wiki habe ich nachgelesen, dass man Text so fett druckt:
„Dieser Textabschnitt wird _Fett_ dargestellt.“

Eigentlich gar nicht so schwer oder? Naja das habe ich dann probiert und es hat, aufgepasst, geklappt :). Yeah! Nur fande ich es etwas nervig immer selbst die Unterstriche hinzufügen zu müssen.
Dazu könnte man doch eine Funktion schreiben?

// Diese Funktion gibt fett gedruckten Text zurück
function boldText(text)
{
return '_'+text+'_';
}

Cool oder?
Jetzt muss ich nicht immer selbst die Unterstriche einfügen. Das macht jetzt die Funktion für mich.

Text farbig drucken:
Ihr ahnt es sicher schon. Auch hierzu habe ich etwas im Wiki gefunden.
Farbiger Text funktioniert so:
„Dieser Text ist °R°rot°r° mit etwas °B°blau°r° gemischt und vielleicht mit ein wenig °[255,100,0]°orange°r°.“

Hmm mal überlegen. Was passiert hier? Ich hab das auch nicht sofort verstanden. Bis ich die Worte mit verschiedenen Farben verglichen habe.
Das was in Kringeln vor dem farbigen Wort steht definiert immer die Farbe. °R° also rot. °B° blau und °[255,100,0]° ein orangener Farbton. Ganz richtig. Wir können auf Knuddels eigene Farben benutzen :).
Wer das nicht will findet hier alle Standartfarben.
Was steht dann hinter dem Wort? Das °r° hinter dem Wort setzt die Farbe auf die Standartfarbe schwarz zurück. Würde ich das weglassen wäre der gesamte Text rot, blau oder eben orange.

// Diese Funktion gibt rot gedruckten Text zurück
function redText(text)
{
return '°R°'+text+'°r°';
}

Soweit so gut 🙂
Als ich die Funktionen definiert hatte musste ich mich nur noch entscheiden, was ich denn nun fett oder rot drucke.
Ich hab mich für die Meldung „Diese Runde ist leider vorbei“ und die neue Aufgabe entschieden. Wobei ich die neue Aufgabe am besten in rot drucken wollte.
Umgesetzt habe ich das dann so:

publicMessage(boldText('____________________ DIESE RUNDE IST LEIDER VORBEI _______________________'));
publicMessage(boldText('Die neue Aufgabe lautet: Was ergibt ' + redText(equation)));

Stop mal!
Was bedeutet die Funktion publicMessage?
Auch hier habe ich die App ein wenig vereinfacht.
Über die Funktion publicMessage(text) schreibt der Appbot immer eine öffentliche Nachricht in den Channel.

function publicMessage(text)
{
appBot.sendPublicMessage(text);
}

Bevor ich es vergesse:
Für private Nachrichten habe ich auch so eine Funktion geschrieben.

function privateMessage(text, user)
{
user.sendPrivateMessage(text);
}

Das war es auch schon. Zumindest für diesen Blog Eintrag.
Ich finde die App ist jetzt schon viel übersichtlicher.
Schreib mir doch was du davon hälst.

Liebe Grüße, MarvinDerPraktikant.