001package votorola.s.gwt.scene.axial; // Copyright 2010, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.
002
003import java.util.HashMap;
004import votorola.s.gwt.scene.*;
005import votorola.s.gwt.scene.feed.*;
006import votorola.s.gwt.scene.dum.*; // see 'temp'
007import votorola.s.gwt.stage.poll.*;
008import votorola.g.hold.*;
009
010
011/** A scene that situates polls in three dimensions according to activity (x), consensus (y)
012  * and turnout (z).
013  */
014public final class TriaxialPollMap implements Scene, Hold
015{
016
017
018    /** Constructs a TriaxialPollMap.  Call {@linkplain #release release}() when done with it.
019      */
020    public TriaxialPollMap()
021    {
022        for( final String pollName: Dummy.POLL_NAME_ARRAY ) // temp, FIX by asking server
023        {
024            polls.put( /*key*/pollName, new MappedPoll( pollName ));
025        }
026    }
027
028
029
030   // ````````````````````````````````````````````````````````````````````````````````````
031   // init for early use
032
033
034    private Spool spool = new Spool1();
035
036
037
038   // ------------------------------------------------------------------------------------
039
040
041    /** Tests whether the specified poll is within the current scope of this map.
042      *
043      *     @see #inScope(BiteJS)
044      */
045    boolean inScope( final MappedPoll poll )
046    {
047        final float x = poll.x();
048        if( x < scoping.xMin() || x > scoping.xMax() ) return false;
049
050        final float y = poll.y();
051        if( y < scoping.yMin() || y > scoping.yMax() ) return false;
052
053        return true;
054    }
055
056
057
058    /** All known polls, keyed by poll name.
059      *
060      *     @see Dummy#POLL_NAME_ARRAY
061      */
062    HashMap<String,MappedPoll> polls() { return polls; }
063
064
065        private final HashMap<String,MappedPoll> polls = new HashMap<String,MappedPoll>();
066
067
068
069    /** The scoping model for this map.
070      */
071    DiaxialScoping scoping() { return scoping; }
072
073
074        private final DiaxialScoping scoping = new DiaxialScoping( spool );
075
076
077
078   // - H o l d --------------------------------------------------------------------------
079
080
081    public void release() { spool.unwind(); }
082
083
084
085   // - S c e n e ------------------------------------------------------------------------
086
087
088    /** {@inheritDoc} Only the x and y axes are variably scoped.  {@linkplain
089      * DiaxialScoping Diaxial scoping} is used for this purpose, q.v. for the format of
090      * the 's' scoping switch.  The z-axis remains unscoped, its full range always in
091      * view.
092      */
093    public boolean inScope( final BiteJS bite )
094    {
095        final PollJS poll = bite.poll();
096        if( poll == null ) return false;
097
098        final String pollName = poll.name();
099        if( pollName == null ) return false;
100
101        final MappedPoll pollM = polls.get( pollName );
102        if( pollM == null ) return false;
103
104        return inScope( pollM );
105    }
106
107
108
109   // ====================================================================================
110
111
112    /** A poll together with its mapping particulars.
113      */
114    static final class MappedPoll
115    {
116
117        private MappedPoll( String _name )
118        {
119            name = _name;
120            x = hash( name, 29 );
121            y = hash( name, 999331 );
122            z = hash( name, 443 );
123        }
124
125
126        private float hash( final String s, final int prime )
127        {
128            int i = 0;
129            for( int c = s.length() - 1; c >= 0; --c )
130            {
131                i = i * prime + s.charAt(c);
132                i |= 0; // truncate to 32 bits when running in browser, where int is actually double
133            }
134
135            float f = Math.abs( i/(float)Integer.MAX_VALUE );
136         // if( f < 0f ) f = 0f;
137         // else if( f >= 1f) f = Math.nextAfter( 1f, 0d ); // exclude 1.0
138         //// 'nextAfter' not available in client, but this is also valid:
139            if( f < 0f || f >= 1f ) f = 0f;
140            return f;
141        }
142
143
144       // --------------------------------------------------------------------------------
145
146
147        /** The name of this mapped poll.
148          *
149          *     @see <a href='pol.xht#poll-id-service'>http://reluk.ca/project/_/outcast/pol.xht#poll-id-service</a>
150          */
151        public String name() { return name; }
152
153            private final String name;
154
155
156        /** The x-axis hash of the poll name.
157          *
158          *     @return a number between 0.0 inclusive and 1.0 exclusive.
159          */
160        float x() { return x; }
161
162            private final float x;
163
164
165        /** The y-axis hash of the poll name.
166          *
167          *     @return a number between 0.0 inclusive and 1.0 exclusive.
168          */
169        float y() { return y; }
170
171            private final float y;
172
173
174        /** The z-axis hash of the poll name.
175          *
176          *     @return a number between 0.0 inclusive and 1.0 exclusive.
177          */
178        float z() { return z; }
179
180            private final float z;
181
182
183       // - O b j e c t ------------------------------------------------------------------
184
185
186        public @Override String toString()
187        {
188            return "mapped poll " + name + "(" + x + "," + y + "," + z + ")";
189        }
190
191
192
193    }
194
195
196
197}