<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Luxi Sans'; font-size:11pt; font-weight:400; font-style:normal;">Hi Bert,<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>After 3 weekend delay I got back today to FreeCell. I re-read the email thread and put together high level steps of how FreeCell's statistics state could be managed. I hope the steps are uderstandable, and realize architecturally it is not very nice, but a step.. <br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Below, I am listing base code (additions and patches) that would plugin FreeCell into the workflow so that everything is in place where it's statistics state could be managed, serialized and stored in Datastore. Could you comment if the following would work as a first step to play with the Datastore stuff in FreeCell - Thanks.  There are some questions at the end, and I appreciate any suggestions and alternatives :)<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>1) Patch SugarLauncher&gt;&gt;#startUp to call<br>
        self class allInstances do: [:ea| ea shutdown]. "is this neded?"<br>
        parameters at 'ACTIVITY_ID' ifPresent: [:activityId|<br>
                objectId := "todo get objectId".<br>
                "Make FreeCell and recover statistics from journal"<br>
                FreeCell class startUpInSugarForActivity: activityId object: objectId.<br>
                World windowEventHandler: self.<br>
        ].<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>        (A note: I realize you suggested to use FREECELL_ACTIVITY_ID and FREECELL_OBJECT_ID instead of ACTIVITY_ID and OBJECT_ID and then we would not have to patch SugarLauncher&gt;&gt;#startup, but it seems we probably need to patch some other SugarLauncher methods such as invite anyway, so I thought this could be ok)<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>2) Add method FreeCell class&gt;&gt;#startUpInSugarForActivity: activityId object: objectId<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p> which would perform the steps currently performed in the FreeCell.st doits:<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>        Project current flapsSurpressed: true.<br>
        World color: Color black.<br>
        FreeCell <br>
                instance <br>
                (recoverStatisticsOnSugarStartUpForActivity: activityId object: objectId)<br>
                openInWorld.<br>
        (... center and zoom to screen extent)<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>3) Add method FreeCell class&gt;&gt;#instance<br>
        FreeCellSingleton := FreeCell new. "just a class var"<br>
        ^ FreeCellSingleton.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>4) Add method FreeCell&gt;&gt;#recoverStatisticsOnSugarStartUpForActivity: activityId object: objectId <br>
        this method is eventually called from patched SugarLauncher&gt;&gt;#startUp, and it would do:<br>
                - use activityId and objectId to read Datastore, and obtain value for key=serialized_statistics<br>
                - obtain sessionWins, sessionLosses, totalWins ... etc from serialized_statistics_value<br>
                - set the deserialized values on the FreeCellStatistics members. (This will need a simple setter of the statistics values)<br>
        <br>
5) Patch SugarLauncher&gt;&gt;#shutDown as follows:<br>
        activityId := parameters at: ACTIVITY_ID.<br>
        objectId := parameters at: OBJECT_ID.<br>
        freeCell := FreeCell instance.<br>
        freeCell #shutDownInSugarAsActivity: activityId object: objectId.<br>
        <br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>6) Add method FreeCell&gt;&gt;#shutDownInSugarAsActivity: activityId object: objectId <br>
        which would :<br>
                - serialize sessionWins, sessionLosses, totalWins ... etc to serialized_statistics_value<br>
                - put on Datastore, for activityId and objectId, an entry with key=serialized_statistics, value=serialized_statistics_value<br>
        <br>
7) Add method FreeCell&gt;&gt;#quit which would do:<br>
        Sugarlauncher current quit<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>8) Patch SugarLauncher&gt;&gt;#quit to call<br>
        self leaveSharedActivity. "is this needed?"<br>
        Smalltalk quitPrimitive. "i hope this calls shutDown?"<br>
        <br>
        FreeCell class startUpInSugar.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>9) Export the changes to FreeCell.st. so it will contain roughtly:<br>
        - patches for:<br>
                - SugarLauncher&gt;&gt;#startUp <br>
                - SugarLauncher&gt;&gt;#shutDown <br>
                - SugarLauncher&gt;&gt;#quit<br>
                - FreeCell&gt;&gt;#quit<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>I did not run any of this .. this is my next step, but I wanted to run it by you for obvious problems, so:<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Questions, comments and doubts:<br>
=============================<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>- Would this work in principal? I am especially not sure around handling the shutDown on quit.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>- Are there better more elegant/reusable ways if someone else wants to do something similar to other Etoys activity (ZIP, Speach etc etc)?<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>- In step 6, what would be the mime type for the new datastore record, so it is associated with Etoys? There are Mime types listed in /usr/share/sugar/data/mime.defaults but it does not list Etoys...<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>- I need to check when etoys start SugarLauncher&gt;&gt;#startUp is performed when I click on a Journal FreeCell item, as startUp contains the FreeCell creation and initialization mechanism<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>- I cannot figure out which class puts the ACTIVITY_ID to AbstractLauncher&gt;&gt;member parameters, but that is not needed for the stuff above.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Thanks Milan<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>PS:<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>A few weeks ago I also investigated a way to make a Squeak based KDE4 Plasmoid ("applet" running in the Plasma container) and manage the Squeak Plasmoid only via DBus. It turns out that, for some likely misguided performance concerns, Plasmoids are not managed by their container via DBus, but rather internal Qt API. So what I thought would be neet is likely not possible without some sort of wrapper, and probably out of reach for practical time considerations, so I will ignore that part. (Maybe possible in gnome..)<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>=======================<br>
old part<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>On May 5, 2009, Bert Freudenberg wrote:<br>
&gt; On 05.05.2009, at 07:27, Milan Zimmermann wrote:<br>
&gt; &gt; On May 4, 2009, Bert Freudenberg wrote:<br>
&gt; &gt; &gt; On 04.05.2009, at 07:31, Milan Zimmermann wrote:<br>
&gt; &gt; &gt; &gt; Hi Bert,<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; I finally did some investigation into Squeak interaction with<br>
&gt; &gt;<br>
&gt; &gt; DBus and<br>
&gt; &gt;<br>
&gt; &gt; &gt; &gt; Datastore. I went through the classes that implement the DBus and<br>
&gt; &gt; &gt; &gt; Datastore<br>
&gt; &gt; &gt; &gt; interaction. This is some great stuff! Among others, if I<br>
&gt; &gt;<br>
&gt; &gt; understand<br>
&gt; &gt;<br>
&gt; &gt; &gt; &gt; this correctly, your Squeak DBus client framework could, for<br>
&gt; &gt; &gt; &gt; example, allow to use Squeak to write a KDE or gnome panel applet?<br>
&gt; &gt; &gt; &gt; But that is an aside.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Yes indeed.<br>
&gt; &gt;<br>
&gt; &gt; Very cool. I think such functionality could also add interest in<br>
&gt; &gt; Squeak... Would it makes sense to add Squeak to this list<br>
&gt; &gt;<br>
&gt; &gt; http://www.freedesktop.org/wiki/Software/DBusBindings<br>
&gt; &gt; ?<br>
&gt;<br>
&gt; Yes. This would be the official page for it:<br>
&gt;<br>
&gt; http://squeaksource.com/dbus.html<br>
&gt;<br>
&gt; &gt; &gt; A fun way to explore it is to run Squeak on a regular KDE/<br>
&gt; &gt; &gt; Gnome desktop and open the DBus Explorer from the World menu. You<br>
&gt; &gt;<br>
&gt; &gt; can,<br>
&gt; &gt;<br>
&gt; &gt; &gt; for example, find the screen saver on the session bus and tell it to<br>
&gt; &gt; &gt; blank the screen ...<br>
&gt; &gt;<br>
&gt; &gt; Or exiting any application :) This is worth a blog by itself.<br>
&gt;<br>
&gt; Oh, nice idea. Announce it on squeak-dev, too. And maybe have your<br>
&gt; blog (or the posts tagged with "squeak") added to planet.squeak.org ...<br>
&gt;<br>
&gt; &gt; World Menu -&gt; Open -&gt; DbusExplorer.<br>
&gt; &gt; Expand DBus sessionBus<br>
&gt; &gt; open KDE system konsole<br>
&gt; &gt; org.kde.konsole/konsole/MainWindow_1/actions/file_quit/<br>
&gt; &gt; com.Trolltech.QT.QAction.trigger<br>
&gt; &gt; yellow(middle or right)-click, select "invoke method"<br>
&gt; &gt; konsole gone<br>
&gt; &gt; Neat...<br>
&gt;<br>
&gt; Hehe. Did you notice you can even invoke methods with arguments?<br>
&gt;<br>
&gt; &gt; &gt; Well. IMHO we should *not* save the whole project to the Journal.<br>
&gt; &gt;<br>
&gt; &gt; This<br>
&gt; &gt;<br>
&gt; &gt; &gt; is not supposed to be an Etoys activity, but a Squeak application.<br>
&gt; &gt;<br>
&gt; &gt; It<br>
&gt; &gt;<br>
&gt; &gt; &gt; should only store and retrieve its relevant state. For starters I'd<br>
&gt; &gt; &gt; only store the statistics, which is about 10 numbers.<br>
&gt; &gt;<br>
&gt; &gt; I did not think of saving only the state of the game, but it is<br>
&gt; &gt; definitely a better approach. Maybe I am missing something here<br>
&gt; &gt; though. For example, in Etoys, saving a project writes the whole<br>
&gt; &gt; project as a pr file - I assume .PR is some for of serialized<br>
&gt; &gt; everything in the project, not just what have changed.<br>
&gt;<br>
&gt; Yes, it writes out pretty much everything reachable from "Project<br>
&gt; current".<br>
&gt;<br>
&gt; &gt; When attempting to store only FreeCell's state, I have a few things<br>
&gt; &gt; to learn and understand:<br>
&gt; &gt; - without looking I am surptised FreeCell's state is only 10<br>
&gt; &gt; numbers, it seems that position of the cards must be more than that<br>
&gt; &gt; unless it's packed somehow - I will look<br>
&gt;<br>
&gt; No, that is only the statistics. Not sure how useful it is to store<br>
&gt; the entire state.<br>
&gt;<br>
&gt; &gt; - which objects represent the state stored<br>
&gt; &gt; - how to serialize it (well that should be relatively<br>
&gt; &gt; straightforward knowing the objects)<br>
&gt; &gt; - what method will write the serialized FreeCell state to Journal<br>
&gt; &gt; instead of<br>
&gt; &gt; SugarDatastoreDirectory&gt;&gt;#writeProjectinFileNamed:fromDirectory:<br>
&gt;<br>
&gt; In FreeCell.st I patch SugarLauncher&gt;&gt;quit which normally would store<br>
&gt; the project, so nothing is stored but the activity simply quits.<br>
&gt;<br>
&gt; This is triggered either by pressing the stop button in the tool bar,<br>
&gt; or by a #windowClose event the launcher receives because in its<br>
&gt; #startUp method it registered itself for these events:<br>
&gt;<br>
&gt;         World windowEventHandler: self.<br>
&gt;<br>
&gt; So if we replace the SugarLauncher mechanism we should register these<br>
&gt; events to be sent to FreeCell instead.<br>
&gt;<br>
&gt; &gt; - what does assign the "ownership" of that file on Journal as FreeCell<br>
&gt;<br>
&gt; Just the meta data properties, in particular the "activity" property.<br>
&gt; See<br>
&gt;<br>
&gt; http://wiki.laptop.org/go/Low-level_Activity_API#Meta_Data<br>
&gt;<br>
&gt; &gt; - how to deserialize the state<br>
&gt; &gt; - how to import it back to the game<br>
&gt; &gt;<br>
&gt; &gt; &gt; The regular Etoys Sugar startup happens in SugarLauncher&gt;&gt;startUp.<br>
&gt; &gt;<br>
&gt; &gt; yes<br>
&gt; &gt;<br>
&gt; &gt; &gt; There it looks for the ACTIVITY_ID parameter to see if we are<br>
&gt; &gt;<br>
&gt; &gt; actually<br>
&gt; &gt;<br>
&gt; &gt; &gt; running under Sugar, and an OBJECT_ID which is present if we are<br>
&gt; &gt; &gt; resuming a Journal entry.<br>
&gt; &gt;<br>
&gt; &gt; yes<br>
&gt; &gt;<br>
&gt; &gt; &gt; I think the best way would be to use different parameter names in<br>
&gt; &gt; &gt; FreeCell.sh, perhaps FREECELL_ACTIVITY_ID and FREECELL_OBJECT_ID.<br>
&gt; &gt;<br>
&gt; &gt; Then<br>
&gt; &gt;<br>
&gt; &gt; &gt; the Etoys logic would not kick off<br>
&gt; &gt;<br>
&gt; &gt; logic in SugarLauncher.startup?<br>
&gt;<br>
&gt; Yes, because that looks for ACTIVITY_ID and OBJECT_ID.<br>
&gt;<br>
&gt; &gt; &gt; and would not try to open the<br>
&gt; &gt; &gt; object as project, but we could provide our own startup method<br>
&gt; &gt;<br>
&gt; &gt; that we<br>
&gt; &gt;<br>
&gt; &gt; &gt; would simply call at the end of FreeCell.st.<br>
&gt; &gt;<br>
&gt; &gt; and load the state read from the Datastore/Journal?<br>
&gt;<br>
&gt; Right, if the FREECELL_OBJECT_ID parameter is present it would hold<br>
&gt; the object id to load.<br>
&gt;<br>
&gt; &gt; &gt; &gt; 4) Ability to start using the black Launcher ribbon on top, with<br>
&gt; &gt;<br>
&gt; &gt; the<br>
&gt; &gt;<br>
&gt; &gt; &gt; &gt; standard Etoys project name a project stop widget that would call<br>
&gt; &gt; &gt; &gt; the commands from 1 and 2. .<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Well if you look at the end of FreeCell.st you see the tool bar is<br>
&gt; &gt; &gt; explicitly toggled off. Before re-enabling it we would have to<br>
&gt; &gt; &gt; customize it (see class SugarNavigatorBar).<br>
&gt; &gt;<br>
&gt; &gt; Ah I thought the bar was SugarLauncher. Another thing to look at.<br>
&gt;<br>
&gt; No, SugarLauncher is registered with the AutoStart class, just like<br>
&gt; the ProjectLauncher which handles the regular Etoys startup (like<br>
&gt; loading a project in the browser plugin etc.).<br>
&gt;<br>
&gt; SugarLauncher handles all the Sugar-related session tasks - datastore,<br>
&gt; collaboration, etc. It's not a pure launcher anymore and probably<br>
&gt; should be factored into some more specific classes.<br>
&gt;<br>
&gt; &gt; I am actually quite excited about this - you did lots of great stuff<br>
&gt; &gt; there that deserves attention, use, and maybe we can do some<br>
&gt; &gt; marketing for it :) by having a few blogs and a small tutorial at<br>
&gt; &gt; some point. Long time ago I played with DCOP in KDE and Dbus is<br>
&gt; &gt; similar but that's not the point - The point is that apart from it's<br>
&gt; &gt; usefulness for Sugar, what you did can be also used for Squeak /<br>
&gt; &gt; Etoys applications to be integral part of KDE and Gnome desktops<br>
&gt; &gt; (perhaps even OS X - I am reading Dbus is ported there there but<br>
&gt; &gt; probably not integrated). I especially like the idea trying to write<br>
&gt; &gt; a KDE Panel applet in Squeak :)<br>
&gt;<br>
&gt; Sounds like a fun thing to try, yes :)<br>
&gt;<br>
&gt; - Bert -<br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Etoys mailing list<br>
&gt; Etoys@lists.laptop.org<br>
&gt; http://lists.laptop.org/listinfo/etoys<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p></body></html>