<?xml version="1.1" ?>
<diagram author="Simon Van Mierlo+Raphael Mannadiar" name="Bouncing_Balls_Python_Version">
    <description>
        Tkinter frame with bouncing balls in it.
    </description>
    <top>
        import random, sys, os
    </top>
    <class name="MainApp" default="true">
        <relationships>
            <association name="fields" class="Field" />
        </relationships>
        <constructor>
            <parameter name="fields_to_create" />
            <parameter name="balls_to_create" />
            <body>
                <![CDATA[
                self.fields_to_create = fields_to_create
                self.balls_to_create = balls_to_create
                self.nr_of_fields = 0
                ]]>
            </body>
        </constructor>
        <scxml initial="running">
            <state id="running" initial="root">
                <parallel id="root">
                    <state id="cd_behaviour" initial="waiting">
                        <state id="waiting">
                            <transition event="create_field" target="../creating">
                                <raise scope="cd" event="create_instance">
                                    <parameter expr='"fields"' />
                                    <parameter expr='"Field"' />
                                    <parameter expr="self.balls_to_create" />
                                </raise>
                            </transition>
                        </state>
                        <state id="creating">
                            <transition event="instance_created" target="../waiting">
                                <parameter name="association_name" type="string"/>
                                <raise scope="cd" event="start_instance">
                                    <parameter expr="association_name" />
                                </raise>
                                <script>
                                    self.nr_of_fields += 1
                                </script>
                            </transition>
                        </state>
                    </state>
                    <state id="spawn_windows" initial="spawning">
                        <state id="spawning">
                            <transition target="." after="0.1" cond="self.nr_of_fields &lt; self.fields_to_create">
                                <raise event="create_field" />
                            </transition>
                            <transition target="../stopped_spawning" cond="self.nr_of_fields &gt;= self.fields_to_create" />
                        </state>
                        <state id="stopped_spawning" />
                    </state>
                    <state id="killer" initial="killing">
                        <state id="killing">
                            <transition after="5" target=".">
                                <script>
                                    print "cpu usage for %i fields with %i balls: %.5f" % (self.fields_to_create, self.balls_to_create, os.times()[0] / 5.0)
                                    sys.exit()
                                </script>
                            </transition>
                        </state>
                    </state>
                </parallel>
                <state id="stopped" />
            </state>
        </scxml>
    </class>

    <class name="Field">
        <relationships>
            <association name="balls" class="Ball" />
            <association name="parent" class="MainApp" min="1" max="1" />
        </relationships>
        <constructor>
            <parameter name="balls_to_create" />
            <body>
                <![CDATA[
                self.balls_to_create = balls_to_create
                self.nr_of_balls = 0
                ]]>
            </body>
        </constructor>
        <scxml initial="root">
            <state id="root" initial="running">
                <parallel id="running">
                    <state id="main_behaviour" initial="running">
                        <state id="running">
                            <transition event="spawn_ball" target="../creating">
                                <parameter name="x" />
                                <parameter name="y" />
                                <raise scope="cd" event="create_instance">
                                    <parameter expr='"balls"' />
                                    <parameter expr='"Ball"' />
                                    <parameter expr="x" />
                                    <parameter expr="y" />
                                </raise>
                            </transition>
                        </state>
                        <state id="creating">
                            <transition event="instance_created" target="../running">
                                <parameter name="association_name" type="string"/>
                                <raise scope="cd" event="start_instance">
                                    <parameter expr="association_name" />
                                </raise>
                                <script>
                                    self.nr_of_balls += 1
                                </script>
                            </transition>
                        </state>
                    </state>
                    <state id="spawn_balls" initial="spawning">
                        <state id="spawning">
                            <transition target="." after="0" cond="self.nr_of_balls &lt; self.balls_to_create">
                                <raise event="spawn_ball">
                                    <parameter expr="150" />
                                    <parameter expr="150" />
                                </raise>
                            </transition>
                            <transition target="../stopped_spawning" cond="self.nr_of_balls &gt;= self.balls_to_create" />
                        </state>
                        <state id="stopped_spawning" />
                    </state>
                </parallel>
                <state id="deleting">
                    <transition target="../deleted">
                        <raise event="delete_field" scope="narrow" target="'parent'">
                            <parameter expr='self.association_name' />
                        </raise>
                    </transition>
                </state>
                <state id="deleted" />
            </state>
        </scxml>
    </class>
    
    <class name="Ball">
        <relationships>
            <association name="parent" class="Field" min="1" max="1" />
        </relationships>
        <constructor>
            <parameter name="x" />
            <parameter name="y" />
            <body>
                <![CDATA[
                self.r = 20.0;
                self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
                self.mouse_pos = {};
                self.smooth = 0.4; # value between 0 and 1
                self.pos = {'x': x, 'y': y}
                ]]>
            </body>
        </constructor>
        <scxml initial="main_behaviour">
            <state id="main_behaviour" initial="bouncing">
                <state id="bouncing">
                    <transition after="(20 - self.getSimulatedTime() % 20) / 1000.0" target=".">
                        <script>
                            <![CDATA[
                            self.pos
                            if self.pos['x'] - self.r <= 0 or self.pos['x'] + self.r >= 800 :
                                self.vel['x'] = -self.vel['x'];
                            if self.pos['y'] - self.r <= 0 or self.pos['y'] + self.r >= 600 :
                                self.vel['y'] = -self.vel['y'];
                            self.pos['x'] += self.vel['x']
                            self.pos['y'] += self.vel['y']
                            ]]>                            
                        </script>
                        <raise event="test" scope="narrow" target="'parent[0]'" />
                    </transition>
                </state>
            </state>
        </scxml>
    </class>
</diagram>
