draft for seat plans
authorKonrad Rosenbaum <konrad@silmor.de>
Mon, 2 Dec 2013 17:13:25 +0000 (18:13 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Mon, 2 Dec 2013 17:13:25 +0000 (18:13 +0100)
doc/seatplans.txt [new file with mode: 0644]
pack
wob/classes/event.wolf
wob/classes/order.wolf
wob/classes/seatplan.wolf [new file with mode: 0644]
wob/db/cart.wolf
wob/db/db.wolf
wob/magicsmoke.wolf

diff --git a/doc/seatplans.txt b/doc/seatplans.txt
new file mode 100644 (file)
index 0000000..42eaa0d
--- /dev/null
@@ -0,0 +1,187 @@
+Seat-Plans
+===========
+
+Server Side Minimum:
+---------------------
+
+<SeatPlan version="1">
+  <Group capacity="123" id="pr" name="Premium" numbered="no" price="1 3"/>
+  <Group capacity="234" id="ch" name="Cheapo" numbered="no" price="2 4"/>
+</SeatPlan>
+
+In this simplest form there are two kinds of seats: "Premium" and "Cheapo".
+In both cases seats are unnumbered (i.e. audience members can chose freely).
+
+<SeatPlan> defines the complete plan
+  version - version number of this spec, it is generally assumed that newer
+    versions are backwards compatible
+<Group> defines one group of seats
+  capacity - specifies how many seats there are in this group
+  id - automatically generated ID for groups, must only contain letters and 
+    digits, max. 8 chars, no spaces
+  name - human readable name for the group
+  numbered - "yes": the seats have numbers, "no" audience members can freely chose
+  price - space separated list of pricecategory IDs for price levels that can be
+    sold in this group, if missing: all categories of the event
+    
+
+To number seats by row add Row-elements to the Group tag:
+
+<SeatPlan version="1">
+  <Group capacity="123" id="pr" name="Premium" numbered="yes">
+    <Row id="2" capacity="23" first="2"/>
+    <Row id="3" capacity="25"/>
+    <Row id="4" capacity="25"/>
+    <Row id="5" capacity="25"/>
+    <Row id="6" capacity="25"/>
+  </Group>
+  <Group name="Expensive" id="ex" numbered="yes">
+    <Row id="" capacity="25"/>
+    <Row id="" capacity="25" first="26"/>
+  </Group>
+  <Group capacity="234" id="ch" name="Cheapo" numbered="no"/>
+</SeatPlan>
+
+In this case the Premium Group consists of rows 2..6, with row 2 numbered 2..24
+and rows 3..6 numbered 1..25 each. The capacity attribute of the Group tag must
+match the sum of row capacities.
+
+<Row> defines a single row of seats inside this group
+  id - a free form ID for the row, must only contain letters and digits,
+    may be empty, but no spaces
+  capacity - number of seats in this row
+  first - a number if counting does not start at 1
+
+If two rows have identical IDs then the seat numbers in those rows must be unique.
+E.g. above: in the Expensive group above both rows use the empty ID, one of them
+has seats 1..25, the other 26..50. If both had for example a seat 25, then only one
+of those two seats could be sold, the other would be inaccessible.
+
+Rows are ignored for unnumbered groups, they may exist to generate graphical 
+seat plans (see below).
+
+Groups may exist several times with different rows/seats. If this happens the
+group id, name, and numbering attributes must be identical on all instances.
+Graphical information may differ. Seats inside those instances must be
+unique (different row id and/or seat number).
+
+Seat Numbering
+----------------
+
+Seat numbers are stored as strings (max. 32 chars). They are constructed from:
+ * the group ID
+ * the row ID, or an empty string if there are no rows defined
+ * the seat number within the row or group
+ * fields are separated by colons
+
+E.g.:
+ "pr:2:13" - group "pr" (Premium above), row "2", seat number 13
+ "ex::42" - group "ex", row with empty ID, seat number "42"
+ "ch::" - group "ch", no numbering
+
+
+Graphical Seat Plans
+---------------------
+
+This part is never evaluated by the server, only by displays:
+
+<SeatPlan version="1" size="100 200">
+  <Group capacity="123" id="pr" name="Premium" numbered="yes" geo="0 20 100 100" bgcolor="#fcc">
+    <Row id="2" capacity="23" first="2" geo="10 0 90 10/>
+    <Row id="3" capacity="25" geo="0 20 100 30"/>
+    <Row id="4" capacity="25" geo="0 40 100 50"/>
+    <Row id="5" capacity="25" geo="0 60 100 70"/>
+    <Row id="6" capacity="25" geo="0 80 100 90"/>
+  </Group>
+  <Group name="Expensive" id="ex" numbered="yes" geo="0 100 100 130" bgcolor="#cfc">
+    <Row id="" capacity="25" geo="0 0 100 10"/>
+    <Row id="" capacity="25" first="26" geo="0 20 100 30"/>
+  </Group>
+  <Group capacity="234" id="ch" name="Cheapo" numbered="no" geo="0 140 100 200" bgcolor="black" fgcolor="white"/>
+</SeatPlan>
+
+New Attributes:
+ SeatPlan/size - relative canvas size, the actual canvas will be scaled to fit the display
+ Group/geo - geometry relative to the canvas, coordinates are: x-left, y-top, x-right, y-bottom
+ Row/geo - geometry relative to the Group
+ bgcolor - (Group/Row) background color
+ fgcolor - (Group/Row) foreground color
+ Group/angle - rotate the group (value in degrees)
+ Row/curve - row curvature, see below
+
+Colors: all web colors can be used by name, numeric values can be specified in hex
+either as "#rgb" or "#rrggbb".
+
+Curvature of Rows: a series of points at which to align seats... ?
+TODO: define trapezes(?), curved rows, etc.
+
+Additional Graphics
+--------------------
+
+The background of the seat plan can be defined in an additional element:
+
+<SeatPlan version="1" size="100 200">
+  <Group capacity="123" id="pr" name="Premium" numbered="yes" geo="0 20 100 100" bgcolor="#fcc"/>
+
+  <!-- create a rectangle -->
+  <Background type="rect" geo="10 10 30 30" bgcolor="yellow"/>
+    
+  <!-- create a simple text -->
+  <Background type="text" geo="10 10 30 30" fgcolor="darkblue" fontsize="15" content="hello"/>
+   
+  <!-- create a circle or elipse -->
+  <Background type="circle" geo="40 40 50 60" bgcolor="lightred"/>
+</SeatPlan>
+
+Attributes:
+  bgcolor - background or fill color (not for Text)
+  fgcolor - foreground (Text) or outline color
+  geo - full size of the shape
+  angle - rotation in degree
+  Text/fontsize - font size in relative points of the seat plan, automatically scaled
+  Text/content - textual content
+
+Specifying Seats in Orders
+---------------------------
+
+No seat specified in cart order:
+1) The system tries to find a group that matches the price category, 
+2) if the category does not have enough seats: continue search at 1
+3) if the category is unnumbered: use it, done
+4) if the category is numbered: try to find continuous seats in the same row
+5) not enough continuous seats: continue searching at 1
+6) if there are no more categories, repeat the search, but allow non-continuous seats
+
+Separately specified rows with the same ID are assumed to be continuous in the order
+of seat numbers. E.ฤก. if seats 1 and 2 of row "1" are specified in a different group than
+seats 3..23, then the algorithm still considers seats 2 and 3 to be side by side.
+
+Specified seats:
+The seat property contains a list of seat numbers (see above), separated by spaces, there must be
+exactly as many seats specified as there are tickets in this line item of the order.
+
+Wildcards:
+Seats can be specified with wildcards:
+ "ex" - chose any row and seat from group "ex"
+ "ex:2" - chose any seat from the row "2" in "ex"
+ "ex:2|3|4" - chose any seat from rows "2", "3" or "4" in "ex"
+ "ex|pr" - chose any seats from groups ex or pr
+ "ex|pr:2" - chose any seats on row "2" that are in group ex or pr
+ "ex|pr:2|3:4" - chose any seat with the number 4 if it is in ex or pr and on rows 2 or 3
+ "ex:2:4|6" - chose seat 4 or 6 from row 2 in group ex
+ "ex:2:4-16" - chose between seats 4 through 16 on row 2 in group ex
+ "*:*:4-16" - chose between seats 4 through 16 on any row in any group
+The algorithm used to select seats is the same as the one for specifying no seats at all,
+except that choices are limited to seats matching the pattern. In fact specifying no seats
+is equivalent to the most unspecific pattern: "" or "*:*:*".
+
+Pattern grouping: "group:row:seat" with "group:row" being equivalent to "group:row:*" and
+"group" equivalent to "group:*" or "group:*:*". The empty pattern "" is equivalent to "*:*:*".
+
+Pattern syntax:
+ "string" - match exactly string
+ "*" - match any value
+ "" - match the empty value only!
+ "s1|s2" - match s1 or s2
+ "1-3" - match any value between 1 and 3 (including), only allowed for seat numbers
\ No newline at end of file
diff --git a/pack b/pack
index de50ef2..e06319c 160000 (submodule)
--- a/pack
+++ b/pack
@@ -1 +1 @@
-Subproject commit de50ef2ddfebf8bf0dc96540d03c51de0213d2a8
+Subproject commit e06319c7261d4189e8bcef16ed50b9739e6e13a5
index 4549075..b9371c3 100644 (file)
                        </Map>
                </Mapping>
        </Class>
-       
+        
+        <Class name="Room">
+                <Abstract lang="php"/>
+                <Property name="id" type="string"/>
+                <Property name="capacity" type="int"/>
+                <Property name="description" type="string"/>
+                
+                <Mapping table="room">
+                        <Map column="roomid" property="id"/>
+                        <Map column="capacity"/>
+                        <Map column="description"/>
+                </Mapping>
+        </Class>
+        
+        <Class name="SeatPlanInfo">
+                <Doc>This class is the transport for seat plans when communicating over the wire</Doc>
+                <Property name="roomid" type="string"/>
+                <Property name="name" type="astring"/>
+                <Property name="plan" type="string"/>
+                <Property name="flags" type="astring"/>
+        </Class>
+                
        <Class name="Event">
                <Abstract lang="qt"/>
                <Abstract lang="php"/>
                        </Map>
                </Mapping>
        </Class>
-       
-       <Class name="Room">
-               <Abstract lang="php"/>
-               <Property name="id" type="string"/>
-               <Property name="capacity" type="int"/>
-               <Property name="description" type="string"/>
-               
-               <Mapping table="room">
-                       <Map column="roomid" property="id"/>
-                       <Map column="capacity"/>
-                       <Map column="description"/>
-               </Mapping>
-       </Class>
 </Wolf>
\ No newline at end of file
index 5def7fb..fc24b32 100644 (file)
@@ -38,6 +38,7 @@
                <Property name="pricecategoryid" type="int"/>
                <Property name="pricecategory" type="PriceCategory"/>
                <Property name="tags" type="string"/>
+                <Property name="seat" type="astring"/>
                
                <Mapping table="ticket">
                        <Map column="ticketid"/>
@@ -46,6 +47,7 @@
                        <Map column="status"/>
                        <Map column="orderid" property="orderid"/>
                        <Map column="tags"/>
+                        <Map column="seat"/>
                        <Map column="pricecategoryid"/>
                        <Map property="pricecategory">
                                <Call lang="php" method="WOPriceCategory::fromTablepricecategory(WTpricecategory::getFromDB($table->pricecategoryid))"/>
diff --git a/wob/classes/seatplan.wolf b/wob/classes/seatplan.wolf
new file mode 100644 (file)
index 0000000..57fd30d
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Seat Plan Definition MagicSmoke WOLF
+  - declares everything needed to define seat plans
+  -
+  - (c) Konrad Rosenbaum, 2013
+  - this file is protected under the GNU AGPLv3 or at your option any newer
+  - see COPYING.AGPL for details
+  -->
+<Wolf>
+        <Class name="SeatPlanRow">
+                <Doc>This is a helper for parsing seat plans: it defines a row of seats</Doc>
+                <Property name="id" type="astring">the ID of this group, if multiple row elements with the same ID exist, they refer to different sections of the same row</Property>
+                <Property name="capacity" type="int">amount of seats in this (part of the) row</Property>
+                <Property name="geo" type="astring">GUI: geometry information for the row</Property>
+                <Property name="bgcolor" type="astring">GUI: background color for seats</Property>
+                <Property name="fgcolor" type="astring">GUI: foreground color, the one the seat number is rendered in</Property>
+                <Property name="first" type="int">number of the first seat in this row</Property>
+        </Class>
+        <Class name="SeatPlanGroup">
+                <Doc>This is a helper for parsing seat plans: it defines a group of rows of seats.</Doc>
+                <Property name="id" type="astring">the ID of this group, if multiple group elements with the same ID exist, they refer to different sections of the same group</Property>
+                <Property name="capacity" type="int">amount of seats in this (part of the) group</Property>
+                <Property name="name" type="astring">human readable name of the group</Property>
+                <Property name="numbered" type="bool">defines whether the group contains numbered seats</Property>
+                <Property name="geo" type="astring">GUI: geometry information for the group</Property>
+                <Property name="bgcolor" type="astring">GUI: background color</Property>
+                <Property name="fgcolor" type="astring">GUI: foreground color, the one the group name is rendered in</Property>
+                <Property name="angle" type="int">GUI: rotation of the group rectangle</Property>
+                <Property name="Row" type="List:SeatPlanRow">definition of rows in this group</Property>
+        </Class>
+        
+        <Class name="SeatPlanBackground">
+                <Property name="type" type="astring">Type of background element, e.g. "circle", "rect", ...</Property>
+                <Property name="geo" type="astring">GUI: geometry information for the group</Property>
+                <Property name="bgcolor" type="astring">GUI: background or fill color</Property>
+                <Property name="fgcolor" type="astring">GUI: foreground, outline or text color</Property>
+                <Property name="angle" type="int">GUI: rotation of the group rectangle</Property>
+                <Property name="fontsize" type="int">GUI: font size for text elements</Property>
+                <Property name="content" type="astring">GUI: textual content</Property>
+        </Class>
+        
+        <Class name="SeatPlan">
+                <Doc>This class is used to parse seat plans on either side.</Doc>
+                <Property name="Group" type="List:SeatPlanGroup"/>
+                <Property name="Background" type="List:SeatPlanBackground"/>
+        </Class>
+</Wolf>
index f5687fe..40aa618 100644 (file)
@@ -36,7 +36,7 @@
                <Column name="eventid" type="int32" notnull="yes" foreignkey="event:eventid" primarykey="yes">the event the ticket is for</Column>
                <Column name="pricecategoryid" type="int32" foreignkey="pricecategory:pricecategoryid" primarykey="yes">the price category of the ticket</Column>
                <Column name="amount" type="int32" notnull="yes">amount of tickets of this type in the cart</Column>
-               <!-- Column name="seating" type="string:32" null="yes"/ -->
+               <Column name="seating" type="string:255" null="yes" version="01.05"/>
        </Table>
        <Table name="cartvoucher" backup="no">
                <Doc>web interface: stores vouchers in the cart</Doc>
index 9276c4b..930d993 100644 (file)
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Main MagicSmoke DB Definition WOLF
   -
-  - (c) Konrad Rosenbaum, 2009-2011
+  - (c) Konrad Rosenbaum, 2009-2013
   - this file is protected under the GNU AGPLv3 or at your option any newer
   - see COPYING.AGPL for details
   -->
 <Wolf>
-       <DataBase instance="db" schema="dbScheme" version="01.04" defaultUpdating="yes">
+       <DataBase instance="db" schema="dbScheme" version="01.05" defaultUpdating="yes">
                <AuditTables>
                        <Column name="audittime" type="int64">Time at which the change was made.
                                <Call lang="php" method="time()"/>
index 5728acb..5f482d9 100644 (file)
@@ -13,7 +13,7 @@
        </Doc>
        <!-- generic settings -->
        <Project baseDir=".." wobDir="wob" name="MagicSmoke" xml-namespace="http://silmor.de/MagicSmoke" auth="session" encoding="wob"/>
-       <Version comm="0100" needcomm="0100" humanReadable="1.91 alpha" target="." system="svn git"/>
+       <Version comm="0101" needcomm="0100" humanReadable="1.91 alpha" target="." system="svn git"/>
        <Include file="db/db.wolf"/>
        
        <!-- configure output -->
@@ -40,6 +40,7 @@
        <Include file="classes/order.wolf"/>
        <Include file="classes/cart.wolf"/>
        <Include file="classes/template.wolf"/>
+        <Include file="classes/seatplan.wolf"/>
        <!-- load and parse transaction definitions -->
        <Include file="transact/basics.wolf"/>
        <Include file="transact/user.wolf"/>