root/trunk/lib/fm/gameobject.rb

Revision 287, 4.8 kB (checked in by ged, 3 months ago)

Checkpoint commit

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Rev Author URL Id
Line 
1#!/usr/bin/ruby
2
3require 'digest/md5'
4require 'logger'
5require 'sync'
6require 'uuidtools'
7
8require 'fm'
9require 'fm/linguistics'
10require 'fm/mixins'
11
12#
13# FaerieMUD::GameObject, an abstract base class for
14# all objects used in the construction of the FaerieMUD game world. It contains
15# variables and functions for tracking the attribution of "creation points" to
16# object authors, the identities of the authors themselves, and utility
17# functions to represent FaerieMUD objects as HTML.
18#
19# == Subversion ID
20#
21# $Id$
22#
23# == Authors
24#
25# * Michael Granger <ged@FaerieMUD.org>
26#
27# :include: LICENSE
28#
29#---
30#
31# Please see the file LICENSE for licensing details.
32#
33class FaerieMUD::GameObject
34        include Sync_m,
35                FaerieMUD::AbstractClass,
36                FaerieMUD::Propertied,
37                FaerieMUD::Loggable,
38                FaerieMUD::Debuggable,
39                FaerieMUD::HTML,
40                FaerieMUD::Linguistics
41
42        ### Class constants
43
44        # SVN Revision
45        SVNRev = %q$Rev$
46
47        # SVN Id
48        SVNId = %q$Id$
49
50        # The total number of "attribution" points for this object.
51        PointTotal = 100
52
53        # The ratio to use when distributing points between contributors.
54        Ratio = 3.0/2.0
55
56
57        #############################################################
58        ###     C L A S S   M E T H O D S
59        #############################################################
60
61        # The authors hash for this class
62        @authors = Hash.new( 0 )
63        @contributors = []
64        class << self
65                attr_reader :authors
66        end
67
68
69        ### Inheritance callback method: Add an 'authors' instance variable to each
70        ### derivative class.
71        def self::inherited( klass )
72                super
73                klass.add_authors_data
74        end
75
76
77        ### Add authors instance data to calling classes
78        def self::add_authors_data
79                unless self.instance_variables.include?( "@authors" )
80                        self.instance_variable_set( :@authors, Hash.new(0) )
81                        self.instance_variable_set( :@contributors, [] )
82                        class << self # :nodoc:
83                                attr_reader :authors
84                        end
85                end
86        end
87
88
89        ### Add one or more authors to the contributors for the current class.
90        def self::contributors( *userids)
91                self.add_authors_data
92                return @contributors if userids.empty?
93                @contributors.replace( userids )
94                chart = self.distribute_points( *userids )
95                self.authors.replace( chart )
96        end
97
98
99        ### Given a list of contributors, distribute points among them in a
100        ### rough 3/2 ratio and return a map of person => points. Thanks to
101        ### stillflame@FaerieMUD.org for the algorithm.
102        def self::distribute_points( *people )
103                points = Array.new( people.nitems, 1 )
104
105                (PointTotal - people.nitems).times do |n|
106                        points.each_with_index do |total,i|
107                                if points[i+1].nil? ||
108                                        total.to_f <= (points[i+1].to_f * Ratio)
109                                        points[i] += 1
110                                        break
111                                end
112                        end
113                end
114
115                chart = Hash.new( 0 )
116                people.each_with_index do |person, i|
117                        chart[person] += points[i]
118                end
119
120                return chart
121        end
122
123
124        ### Versioning method -- return the subversion rev number for the object.
125        def self::rev
126                revno = self.const_get( :SVNRev )
127                if revno.match( /(\d+)/ )
128                        return Integer($1)
129                else
130                        return 0
131                end
132        end
133
134
135        ### Create an example instance of the receiving class. This is used to ease
136        ### the complexity of creating example objects for experimentation. This
137        ### should be overridden by object classes which require instantiation
138        ### arguments.
139        def self::example( args={} )
140                new( args )
141        end
142
143
144        #############################################################
145        ###     I N S T A N C E   M E T H O D S
146        #############################################################
147
148        # This must come after the declaration of the contributors method above.
149        contributors :ged, :stillflame, :phaedrus
150
151        ### Initialize a new FaerieMUD::GameObject. Arguments in the
152        def initialize( args={} )
153                super()
154
155                # Add unique ID, rev, and mutex
156                @id = UUID.timestamp_create
157                @rev = self.class.rev
158
159                # Call setters for named arguments
160                args.each do |method, value|
161                        self.send( "#{method}=", value )
162                end
163        end
164
165
166        ### Copy initializer -- generate a unique id for cloned objects.
167        def initialize_copy( original )
168                super
169                @id = UUID.timestamp_create
170        end
171
172
173        ######
174        public
175        ######
176
177        # The object's unique id
178        attr_reader :id
179        alias_method :uuid, :id
180
181        # The revision number of the class from which the object was instantiated at
182        # the time of its creation or last upgrade.
183        attr_reader :rev
184
185
186        ### Return the number of contribution points for the given +author+ (a
187        ### String) the object is worth.
188        def contribution( author )
189                self.class.authors[ author ]
190        end
191
192
193        ### Obtain a shared lock on the receiver for the duration of the
194        ### block. The mutex object is passed as argument.
195        def readlocked
196                return unless block_given?
197                self.synchronize( Sync::SH ) do
198                        yield
199                end
200        end
201
202
203
204        #########
205        protected
206        #########
207
208        ### Obtain an exclusive lock on the receiver for the durection of the
209        ### block. The mutex object is passed as argument.
210        def writelocked
211                return unless block_given?
212                self.synchronize( Sync::EX ) do
213                        yield
214                end
215        end
216
217end # class FaerieMUD::GameObject
Note: See TracBrowser for help on using the browser.