File Coverage

blib/lib/Art/World.pm
Criterion Covered Total %
statement 832 954 87.2
branch 17 22 77.2
condition 22 138 15.9
subroutine 160 179 89.3
pod 0 24 0.0
total 1031 1317 78.2


line stmt bran cond sub pod time code
1 14     14   865181 use 5.20.0;
  14         176  
2 14     14   66 use strict;
  14         29  
  14         274  
3 14     14   57 use warnings;
  14         30  
  14         913  
4              
5             package Art::World {
6              
7             our $VERSION = '0.19_01';
8              
9             use Zydeco
10 14         191 authority => 'cpan:SMONFF',
11             # Predeclaration of types avoid use of quotes in args types declarations or
12             # signatures. See https://codeberg.org/smonff/art-world/issues/37
13             declare => [
14             'Agent',
15             'Artwork',
16             'Collector',
17             'Event',
18             'Idea',
19             'Place',
20             'Theory',
21             ],
22 14     14   9073 version => $VERSION;
  14         4707044  
23              
24 14     14   421727 use feature qw( postderef );
  14         32  
  14         560  
25 14     14   73 no warnings qw( experimental::postderef );
  14         25  
  14         591  
26 14     14   75 use Carp qw( carp cluck );
  14         24  
  14         890  
27 14     14   74 use utf8;
  14         25  
  14         104  
28 14     14   8141 use Config::Tiny;
  14         13008  
  14         576  
29 14     14   86 use List::Util qw( max any );
  14         55  
  14         912  
30 14     14   6271 use Math::Round;
  14         102976  
  14         939  
31 14     14   104 use Try::Tiny;
  14         28  
  14         1674  
32              
33 14     14   547092 role Abstraction {
  14         32  
  14         126  
  14         325  
34 14         169 has discourse ( type => Str );
  14         560  
35 14         82 has idea! ( type => Str, is => rw, trigger => true );
36 14         337 # BUG if use "imagination" it will always be undef, because it comes alphabetically after "idea" :-/
37 14         104 has _imagination ( type => ArrayRef[ Str ] ) = [];
  2         11062  
  14         42010  
38 14         114 has process ( type => ArrayRef );
  14         367  
39 14         109 has project ( type => Str );
  14         282  
40 14         123 has time ( type => Int );
41 14         273 # Here should exist all the possible interractions of Concept entities
42             method initiate_process {
43 0   0 0 0 0 return $self->idea;
  0         0  
  0         0  
  0         0  
44 0         0 }
  14         299  
45 14         227 method insert_to_file {}
46             # etc.
47 14   0 14 0 7222767 use DDP;
  14     0   416184  
  14         160  
  14         157  
  0         0  
  0         0  
  0         0  
  14         401  
  0         0  
48             method _trigger_idea {
49 3   33 3   6 push $self->_imagination->@*, $self->idea;
  3         12  
  3         6  
  3         1530  
50 3         70 }
51 14     14   23358 }
  14     14   35  
  14         212  
  14         226  
  14         6240  
  14         29  
  14         184  
52              
53 14     14   19091 role Active {
  14         30  
  14         98  
  14         291  
54             method participate {
55 0   0 0 0 0 say "That's interesting";
  0         0  
  0         0  
  0         0  
56 0         0 }
57 14     14   16315 }
  14     14   46  
  14         162  
  14         120  
  14         5234  
  14         40  
  14         52  
58              
59 14     14   36653 role Buyer {
  14         31  
  14         104  
60 14         331  
61 14         84 requires money;
62 14         467  
63             multi method acquire ( Artwork $art ) {
64 4   33     17765 $self->pay( $art, $self );
  4         21  
  4         7  
65 4         17 $art->change_owner( $self );
66 4         164 }
67 14     14   3978992 }
  14     14   37  
  14         274  
  14         200  
  14         6546  
  14         30  
  14         56  
68              
69             # Dunno how but the fact of being collected should bump artist reputation
70 14     14   220439 role Collectionable {
  14         35  
  14         134  
  14         328  
71             has owner (
72 14   33     132 lazy => true,
  1         6937  
  1         5  
  1         17  
73             is => rw,
74             clearer => true,
75             writer => 'set_owner',
76 14         17364 type => ArrayRef[ Agent ]) = $self->creator;
77 14         101 has value ( is => rw );
  14         283  
78             has status (
79 14         104 enum => ['for_sale', 'sold'],
80             # Create a delegated method for each value in the enumeration
81             handles => 1,
82             default => 'for_sale' );
83 14         262  
84             method $remove_from_seller_collection {
85             my $meta = Art::World::Util->new_meta;
86 6   33     11 # Removal of the to-be-sold Artwork in seller collection
  6         15  
  6         9  
87 6         136 for my $owner ( $self->owner->@* ) {
88             # Artists don't have a collection
89 6         186 # Or maybe they can... So we should add a specific case
90             if ( $meta->get_class( $owner ) !~ '^Art::World::Artist$' ) {
91             while ( my ( $i, $art ) = each( $owner->collection->@* )) {
92 9 100       82 # Removing if a matching artwork is found
93 8         141 # Should be removed by id, but we don't manage that yet
94             if ( $art->title =~ $self->title ) {
95             # Wish I would use List::UtilsBy extract_by() for this
96 5 100       112 splice $owner->collection->@*, $i, 1;
97             }
98 3         46 }
99             }
100             }
101             }
102 14         25  
103 14         287 multi method change_owner ( Collector $buyer ) {
  14         270  
104              
105 4   33     17734 # From seller collection
  4         19  
  4         8  
106             $self->$remove_from_seller_collection;
107              
108 4         13 $self->clear_owner;
109             $self->set_owner([ $buyer ]);
110 4         87 push $buyer->collection->@*, $self;
111 4         74 # TODO guess it should bump some people reputation and artwork aura now
112 4         196 }
113 14         410  
114 14         211 multi method change_owner ( Coinvestor $buyers ) {
115 2   33     697  
  2         7  
  2         4  
116             # From Collector point of view
117             $self->$remove_from_seller_collection;
118 2         7  
119             # From Artwork point of view
120             $self->clear_owner;
121 2         45 $self->set_owner( $buyers->members );
122 2         39 push $buyers->collection->@*, $self;
123 2         95 # TODO guess it should bump some people reputation and artwork aura now
124             }
125 14     14   3877754 }
  14     14   36  
  14         234  
  14         129  
  14         5687  
  14         32  
  14         52  
126              
127 14     14   59025 role Collective {
  14         35  
  14         105  
128 14         328  
129 14         149 has members! ( type => ArrayRef[ Agent ] );
130 14         3805  
131             multi method acquire ( Artwork *art, Collective *collective ) {
132 2   33     4146 for my $member ( $arg->collective->members->@* ) {
  2         7  
  2         3  
133 2         10 $member->pay( $arg->art, $arg->collective );
134 4         58 }
135             $arg->art->change_owner( $arg->collective );
136 2         76 }
137 14     14   1402905 }
  14     14   42  
  14         233  
  14         288  
  14         6099  
  14         33  
  14         73  
138              
139              
140 14     14   59314 role Event {
  14         29  
  14         104  
  14         347  
141 14         108 has place ( type => Place );
  14         2620  
142 14         136 has datetime ( type => InstanceOf['Time::Moment'] );
143 14         57044 # "guests"
144 14         117 has participant ( type => ArrayRef[ Agent ] );
  14         2509  
145 14         120 has title ( type => Str, is => ro );
146 14     14   3862309 }
  14     14   45  
  14         245  
  14         5680  
  14         46  
  14         59  
147              
148 14     14   50659 role Exhibit {
  14         36  
  14         108  
  14         382  
149 14         110 has public;
  14         434  
150 14         110 has exhibition ( type => ArrayRef );
  14         410  
151 14         74 has artist ( type => ArrayRef );
  14         330  
152 14         94 has artwork ( type => ArrayRef );
153 14         310  
154             method display {
155 0   0 0 0 0 say "Shoooow";
  0         0  
  0         0  
  0         0  
156 0         0 }
157 14     14   3829801 }
  14     14   35  
  14         237  
  14         169  
  14         6128  
  14         31  
  14         62  
158              
159             # TODO If an Agent work is collected, it's reputation should go up
160 14     14   141795 role Fame {
  14         41  
  14         134  
161 14         340 # Private
162             method $update_fame( Num $difference ) {
163             # Dynamic attribute accessor
164 33   33     71 my $attribute = $self->isa( 'Art::World::Work' ) ?
  33         82  
  33         42  
165             'aura' : 'reputation';
166 33 100       223 if ( $self->can( $attribute )) {
167             if ( $self->$attribute + $difference >= 0 ) {
168 33 50       136 $self->$attribute( $self->$attribute + $difference )
169 33 100       826 } else {
170 32         744 carp 'You tried to update ' . $attribute . ' to a value smaller ' .
171             'than zero. Nothing changed.';
172 1         300 }
173             return $self->$attribute;
174             } else {
175 33         1370 require Art::World::Util;
176             carp 'No such attribute ' . $attribute .
177 0         0 ' or we don\'t manage this kind of entity ' . Art::World::Util->new_meta->get_class( $self );
178 0         0 }
179             }
180 14         26  
181 14         315 multi method bump_fame( PositiveNum $gain ) {
  14         292  
182             $self->$update_fame( $gain );
183 22   33     1487 }
  22         250  
  22         36  
184 22         62  
  14         537  
185 14         203 multi method bump_fame( NegativeNum $loss ) {
186             $self->$update_fame( $loss )
187 8   33     564 }
  8         29  
  8         14  
188 8         21  
  14         261  
189 14         156 multi method bump_fame {
190 3   33     127 $self->$update_fame( $self->config->{ FAME }->{ DEFAULT_BUMP });
  3         15  
  3         7  
191 3         94 }
192 14     14   1299742 }
  14     14   34  
  14         212  
  14         127  
  33         35296  
  14         5824  
  14         33  
  14         62  
193              
194 14     14   28488 role Identity {
  14         35  
  14         109  
  14         361  
195 14         488 has id ( type => Int );
  14         559  
196 14         99 has name ( type => Str );
197 14     14   1897542 }
  14     14   36  
  14         275  
  14         6368  
  14         254  
  14         64  
198              
199             # From the documentation
200             #
201             # A `Place` must `invite()` all kind of `Agents` that produce `Work` or other
202             # kind of valuable social interactions. Depending of the total `reputation` of
203             # the `Place` it will determine it's `underground` status: when going out of
204             # the `underground`, it will become an institution.
205             #
206 14     14   20059 role Invitation {
  14         28  
  14         109  
207             # In case a group of Agents are invited, for an Event like a performance, a
208 14         247 # concert
209             multi method invite ( ArrayRef[ Agent ] *people, Event *event ) {
210 0   0     0 }
  0         0  
  0         0  
211 14     14   25102 }
  14     14   29  
  14         160  
  14         238  
  14         5216  
  14         29  
  14         60  
212              
213             # The idea here is producing discourse about art
214 14     14   19433 role Language {
  14         31  
  14         100  
  14         292  
215             method speak ( Str $paroles) {
216 0   0 0 0 0 say $paroles;
  0   0     0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
217 0         0 # TODO Could write to a log file
218             }
219 14     14   400241 }
  14     14   43  
  14         204  
  14         193  
  14         6359  
  14         31  
  14         60  
220              
221 14     14   40900 role Manager {
  14         34  
  14         112  
  14         337  
222 14         100 has places ( type => ArrayRef[ Place ] );
223 14         16019  
224             method organize {}
225 14         320  
226 14   0 0 0 219 method influence ( Int $reputation) {
  0         0  
  0         0  
  0         0  
  0         0  
227 7   33 7 0 19 return $self->config->{ FAME }->{ MANAGER_BUMP } * $reputation;
  7   66     20  
  7         10  
  7         543  
  7         31  
  7         1712  
  7         119  
228 7         130 }
229 14     14   1394823 }
  14     14   39  
  14         227  
  14         153  
  14         5785  
  14         32  
  14         56  
230              
231 14     14   98383 role Market {
  14         35  
  14         128  
232 14         337  
233 14         135 has money! ( type => Num, is => rw, default => 0 );
234              
235 14         584 # Can be a personal collector or a Coinvestor
236             method pay ( Artwork $piece, Collector $collector ) {
237 8   33 8 0 22 # Divide what must be paid by each buyer
  8   66     36  
  8         15  
  8         33  
  8         44  
  8         2832  
  8         119  
238             my $must_give = Art::World::Util
239 8 100       177 ->new_meta
240             ->get_class( $collector ) !~ /^Art::World::Coinvestor$/ ?
241             $piece->value :
242             $piece->value / scalar $collector->members->@*;
243              
244             # The money must be divided in equal between all owners
245             my $part = $must_give / scalar $piece->owner->@*;
246 8         169 # Seller(s) got their money given
247             map { $_->money( $_->money + $part ) } $piece->owner->@*;
248 8         154 # Buyer gives the money
  12         364  
249             $self->money( $self->money - $must_give );
250 8         376 }
251 14     14   1854352 }
  14     14   36  
  14         279  
  14         227  
  14         6292  
  14         29  
  14         59  
252              
253 14     14   18580 role Showable {
  14         30  
  14         98  
254 14         283 #requires exhibition;
255             method exhibit {
256 0   0 0 0 0 say "Show";
  0         0  
  0         0  
  0         0  
257 0         0 }
258 14     14   15417 }
  14     14   43  
  14         194  
  14         145  
  14         5429  
  14         33  
  14         59  
259              
260 14     14   11842 role Space {
  14         30  
  14         94  
261             # Like a small space or a large space
262 14         359 # Could limit the number of person coming during an event for example
263 14         88 has space;
264 14     14   961552 }
  14     14   42  
  14         248  
  14         6624  
  14         34  
  14         58  
265              
266 14     14   18070 role Underground {
  14         33  
  14         97  
  14         261  
267             method experiment {
268 0   0 0 0 0 say "Underground";
  0         0  
  0         0  
  0         0  
269 0         0 }
270 14     14   15718 }
  14     14   32  
  14         165  
  14         167  
  14         5271  
  14         29  
  14         66  
271              
272 14     14   13225 role Writing {
  14         33  
  14         94  
  14         326  
273             method write ( Theory $concepts ) {}
274 14   0 14 0 404722 }
  14   0 14   35  
  14     0   255  
  14         229  
  0         0  
  0         0  
  0         0  
  14         6241  
  14         32  
  14         208  
  0         0  
  0         0  
  0         0  
  0         0  
275              
276 14     14   1238937 class Art {
  14         36  
  14         171  
  0         0  
277 14         208  
278             has config (
279             is => ro,
280             lazy => true,
281 4         100 default => sub { Config::Tiny->read( './art.conf' )}
282 14         136 );
283              
284             # TODO an implemented project (Work, Exhibition) should inherit of this
285 14         321 # TODO some stuff should extends this
286 14     14   1443081 abstract class Concept {
  14         40  
  14         267  
  14         254  
  14         39  
287 14     14   1244730 class Idea with Abstraction {
  14         36  
  14         173  
  14         401  
  14         38  
  0         0  
288 14         484 method express {
289 0   0 0 0 0 say $self->discourse if $self->discourse;
  0         0  
  0         0  
  0         0  
290 0 0       0 }
291 14     14   22811 }
  14     14   33  
  14         218  
  14         198  
  14         6507  
  14         34  
  14         61  
  14         31  
292 14     14   9841 class Theory with Abstraction { }
  14     14   35  
  14     14   95  
  14         1439  
  14         34  
  14         134  
  14         253  
  14         340  
  14         4563  
  14         33  
  14         63  
293 14     14   819 }
  14     14   29  
  14         135  
  14         332  
  14         4426  
  14         35  
  14         63  
294 14         29  
295 14     14   41325 class Opening with Event, Fame {
  14         39  
  14         125  
  14         407  
  14         29  
296 14         499 has treat ( type => ArrayRef[ Str ]);
  14         134  
  14         3234  
297 14         90 has smalltalk;
298              
299 14         234 # TODO must take as parameter what is served
300             method serve {
301 1   33 1 0 3 return $self->treat->@*;
  1         5  
  1         3  
  1         5657  
302 1         11 }
303 14     14   1971804 }
  14     14   37  
  14         220  
  14         229  
  14         6271  
  14         35  
  14         62  
304              
305 14         24 # TODO Guess this is more like an Agent method or role
306 14     14   7070 class Sex with Event;
  14     14   31  
  14     14   93  
  14         1297  
  14         30  
  14         128  
  14         251  
  14         324  
  14         4438  
  14         33  
  14         53  
307              
308 14         27 # Missing some "World" components
309 14     14   146662 class Playground with Identity {
  14         38  
  14         131  
  14         224  
310 14         22  
311 14     14   32159 class Magazine {
  14         39  
  14         108  
  0         0  
312 14         334  
313 14         108 has reader;
  14         446  
314 14         88 has writer ( type => ArrayRef[ Agent ] );
315 14         3657  
316 14   0 0 0 183 method publish {};
  0         0  
  0         0  
  0         0  
  0         0  
317 14     14   1960440 }
  14     14   34  
  14         241  
  14         6255  
  14         36  
  14         125  
318 14         23  
319 14     14   114513 class Place with Fame, Invitation, Space {
  14         38  
  14         139  
  14         238  
320              
321 14         25 # Like, dunno, a city ? Could be in a Geo role I guess
322 14         115 has location ( type => Str );
  0         0  
323 14         314  
324 14     14   1036685 class Institution with Market {
  14         40  
  14         151  
  14         254  
  14         27  
325 14     14   45364 class Gallery with Exhibit, Buyer {
  14         37  
  14         110  
  14         425  
  14         31  
  0         0  
326 14         490 has artwork ( type => ArrayRef );
  14         116  
  14         573  
327 14         75 has artist ( type => ArrayRef );
  14         371  
328 14         62 has event ( type => ArrayRef );
  14         307  
329 14         66 has owner;
330 14     14   3807975 }
  14     14   41  
  14         250  
  14         6586  
  14         35  
  14         65  
331 14         25  
332 14     14   9641 class Museum with Exhibit, Buyer;
  14     14   32  
  14     14   95  
  14         1425  
  14         34  
  14         133  
  14         247  
  14         322  
  14         4500  
  14         35  
  14         58  
333 14         31  
334 14     14   37531 class School {
  14         30  
  14         114  
335 14         345 # TODO much underground
336 14         87 has student ( type => ArrayRef[ Agent ]);
337 14         3749 # TODO Should enforce a minimum reputation
338 14         87 has teachers ( type => ArrayRef[ Agent ]);;
339 14     14   1878701 }
  14     14   36  
  14         233  
  14         7967  
  14         39  
  14         60  
340 14     14   909 }
  14     14   30  
  14         132  
  14         362  
  14         4237  
  14         36  
  14         55  
341 14         22  
342 14     14   7001 class Squat with Underground;
  14     14   32  
  14     14   88  
  14         1385  
  14         30  
  14         120  
  14         235  
  14         311  
  14         4135  
  14         31  
  14         856  
  14         26  
343 14     14   4281 class Workshop;
  14     14   32  
  14     14   82  
  14         1532  
  14         91  
  14         138  
  14         4295  
  14         28  
  14         56  
344              
345 14     14   794 }
  14     14   25  
  14         114  
  14         307  
  14         4189  
  14         26  
  14         51  
346 14         25  
347 14     14   4221 class Website;
  14     14   24  
  14     14   83  
  14         1135  
  14         25  
  14         157  
  14         4149  
  14         39  
  14         53  
348              
349 14     14   852 }
  14     14   26  
  14         127  
  14         304  
  14         4066  
  14         28  
  14         54  
350 14         22  
351 14     14   451551 class Agent with Active, Fame, Identity {
  14         38  
  14         143  
  14         278  
352 14         29  
353 14         102 has relationship;
  14         315  
  0         0  
354 14         143 has reputation ( is => rw, type => PositiveOrZeroNum ) = 0;
  22         58921  
355             # TODO it would improve a lot the networking
356              
357             # TODO Should be done during an event
358             # TODO In case the networker is a Manager, the reputation bump
359 14         343 # should be higher
360             method networking( ArrayRef $people ) {
361              
362 3   33 3 0 12 my $highest_reputation = max map { $_-> reputation } $people->@*;
  3   66     19  
  3         6  
  3         11590  
  3         36  
  3         2228  
  3         55  
363             my $bump = $highest_reputation > 1 ?
364 3         8 round( $highest_reputation * $self->config->{ FAME }->{ BUMP_COEFFICIENT } / 100) :
  9         213  
365             $self->config->{ FAME }->{ DEFAULT_BUMP };
366             for my $agent ( $people->@* ) {
367 3 50       104 $agent->bump_fame( $bump );
368 3         532 }
369 9         224  
370             if ( any { $_->does( 'Art::World::Manager' ) } $people->@* ) {
371             my @managers = grep { $_->does( 'Art::World::Manager' )} $people->@*;
372 3 50       54 my $highest_influence_manager = max map { $self } @managers;
  7         122  
373 3         58 # Bump all the other persons with the Manager->influence thing
  9         117  
374 3         37 # but not the Manager with the highest influence otherwise it would
  4         18  
375             # increase it's own reputation
376             my @all_the_other = grep { $_->id != $highest_influence_manager->id } $people->@*;
377             for my $agent ( @all_the_other ) {
378 3         7 # The influence() methode is only a way of bumping_fame() with a special bumper
  9         40  
379 3         9 $agent->bump_fame( $highest_influence_manager->influence( $agent->reputation ));
380             }
381 6         121 }
382             }
383 14         252  
384 14     14   2564401 class Artist with Market {
  14         39  
  14         135  
  14         391  
  14         225  
385 14         28  
386 14         467 has artworks ( type => ArrayRef );
  14         128  
  14         523  
387 14         105 has collectors ( type => ArrayRef[ Collector ], default => sub { [] });
  8         67295  
  14         16996  
388 14         134 has collected ( type => Bool, default => false, is => rw );
  14         324  
389             has status (
390             enum => [ 'underground', 'homogenic' ],
391             # Create a delegated method for each value in the enumeration
392             handles => 1,
393             default => sub {
394 11         582 my $self = shift;
395 14 100       122 $self->has_collectors ? 'homogenic' : 'underground' });
  11         51  
396 14         251  
397             method create {
398             say $self->name . " create !";
399 0   0 0 0 0 }
  0         0  
  0         0  
  0         0  
400 0         0  
  14         344  
401 14         198 method have_idea {
402             say $self->name . ' have shitty idea' if true;
403 0   0 0 0 0 }
  0         0  
  0         0  
  0         0  
404 0         0  
  14         224  
405 14         143 method perform {}
406              
407             # factory underground_artist does underground
408              
409 14         221 # TODO Zydeco already provides a shortcut for this through predicates
410 14   0 0 0 124 method has_collectors {
  0         0  
  0         0  
  0         0  
  0         0  
411 11   33 11 0 26 if ( scalar $self->collectors->@* > 1 ) {
  11         49  
  11         20  
  11         49  
412 11 100       226 $self->collected( true );
413 3         57 }
414             }
415 14     14   3943137 }
  14     14   49  
  14         228  
  14         118  
  14         5977  
  14         36  
  14         58  
416 14         27  
417 14     14   52710 class Collector with Active, Buyer, Market {
  14         36  
  14         115  
  14         235  
  14         32  
418 0         0 has collection (
419             type => ArrayRef[ Artwork, 0 ],
420 11         33086 default => sub { [] },
421 14         87 is => rw, );
  14         17485  
422 14     14   994334 class Coinvestor with Collective {
  14         41  
  14         134  
  14         366  
423             # TODO the Coinvestor money should be automatically build from all the
424             # investors
425 14     14   1473 }
  14     14   27  
  14         192  
  14         464  
  14         5840  
  14         31  
  14         60  
426 14     14   942 }
  14     14   33  
  14         126  
  14         320  
  14         4606  
  14         31  
  14         58  
427 14         27  
428 14     14   10854 class Critic with Language, Writing {};
  14     14   28  
  14     14   96  
  14         1446  
  14         33  
  14         144  
  14         300  
  14         335  
  14         4313  
  14         35  
  14         58  
429 14         28  
430 14     14   51670 class Curator with Manager, Writing {
  14         38  
  14         109  
  14         395  
  14         28  
431 14         484 has exhibition( type => ArrayRef );
  14         132  
  14         519  
432             method select( Artwork $art ) {
433 0   0 0 0 0 push $self->exhibition->@*, $art;
  0   0     0  
  0         0  
  0            
  0            
  0            
  0            
434 0         0 }
  14         320  
435 14         244 method define( Theory $thematic ) { }
  14         220  
436 14   0 0 0 155 method setup( Place $space ) { }
  0   0     0  
  0         0  
  0         0  
  14         214  
  0            
  0            
  0            
  0            
437 14   0 0 0 141 method write( Theory $catalog ) { }
  0   0     0  
  0         0  
  0         0  
  0            
  0            
  0            
  0            
438 14   0 14 0 2535949 }
  14   0 14   35  
  14     0   241  
  14         117  
  0         0  
  0         0  
  0         0  
  14         6268  
  14         29  
  14         62  
  0            
  0            
  0            
  0            
439 14         26  
440 14     14   14007 class Director with Manager {
  14         31  
  14         93  
  14         243  
  14         32  
441 14     14   7541 class Gallerist {}
  14     14   30  
  14     14   89  
  14         1205  
  14         29  
  14         144  
  14         4705  
  14         34  
  14         62  
  0         0  
442 14     14   663 };
  14     14   29  
  14         116  
  14         346  
  14         4293  
  14         33  
  14         62  
443 14         27  
444 14     14   26152 class Public with Unserializable? {
  14         32  
  14         105  
  14         378  
445 14         27 # TODO could have an ArrayRef of Agents attribute
446 14         454 method visit( ConsumerOf[ Event ] $event ) {
447 0   0 0 0 0 say "I visited " . $event->title;
  0   0     0  
  0         0  
  0            
  0            
  0            
  0            
448 0         0 }
449 14     14   411057 }
  14     14   35  
  14         223  
  14         197  
  14         6333  
  14         32  
  14         61  
450 14     14   993 }
  14     14   30  
  14         130  
  14         317  
  14         4380  
  14         35  
  14         58  
451              
452              
453 14     14   111429 class Work extends Concept with Fame, Identity {
  14         38  
  14         124  
  14         263  
  14         404  
454 14         31  
455 14         92 has creation_date;
  14         248  
  0         0  
456             has creator!(
457 14         91 is => ro,
458             type => ArrayRef[ Agent ] );
459              
460 14         10118 # TODO it conflicts a bit with the Identity's name attribute
461             has title(
462 14         177 is => ro,
463             type => Str );
464              
465 14         292 # Same as Agent->reputation
466 14         129 has aura( is => rw, type => PositiveOrZeroNum );
467 14         275  
468 14     14   3830773 class Article
  14     14   34  
  14     14   132  
  14         1422  
  14         30  
  14         185  
  14         5998  
  14         33  
  14         444  
469 14         27  
470 14     14   18828 class Artwork with Showable, Collectionable {
  14         33  
  14         92  
  14         467  
  14         33  
471 14         476 has material;
  14         102  
  14         637  
472 14         69 has size;
473 14     14   1878951 }
  14     14   37  
  14         250  
  14         6611  
  14         36  
  14         57  
474 14         26  
475 14     14   4648 class Book;
  14     14   32  
  14     14   90  
  14         1184  
  14         28  
  14         124  
  14         4338  
  14         35  
  14         94  
476              
477             # BUG doesn't have the Work attributes.
478 14         33 # Multiple inheritance is not fine
479 14     14   29033 class Exhibition with Event {
  14         35  
  14         104  
  14         396  
  14         33  
480 14         464 has curator! (
481 14         76 is => ro,
482             type => ArrayRef[ Curator ] );
483 14     14   953611 }
  14     14   39  
  14         521  
  14         23619  
  14         31  
  14         60  
484 14     14   1076 }
  14     14   30  
  14         140  
  14         278  
  14         4367  
  14         36  
  14         60  
485 14     14   756 }
  14     14   30  
  14         138  
  14         4282  
  14         29  
  14         63  
486             }
487              
488             1;
489             __END__
490              
491             =encoding UTF-8
492              
493             =head1 NAME
494              
495             Art::World - Modeling of creative processes
496              
497             =head1 SYNOPSIS
498              
499             use Art::World;
500              
501             my $artwork = Art::World->new_artwork(
502             creator => [ $artist, $another_artist ] ,
503             owner => 'smonff'
504             title => 'Corrupted art institutions likes critical art'
505             value => 100 );
506              
507             my $museum = Art::World->new_museum(
508             money => 1000,
509             name => 'Contemporary Museum of Art::World' );
510              
511             $museum->acquire( $artwork );
512              
513             =head1 DESCRIPTION
514              
515             C<Art::World> is an attempt to model and simulate a system describing the
516             interactions and influences between the various I<agents> of the art world.
517              
518             It tries to draw a schematization of the interactions between art, institutions,
519             influences and unexpected parameters during the social processes of artistic
520             creation.
521              
522             More informations about the purposes and aims of this project can be found in
523             it's L<Art::World::Manual>. Especially, the
524             L<HISTORY|Art::World::Manual/"HISTORY"> and the
525             L<OBJECTIVES|Art::World::Manual/"OBJECTIVES"> section could be very handy to
526             understand how this is an artwork using programming.
527              
528             =head1 MOTIVATIONS
529              
530             This project is a self-teaching experiment around the modern Perl
531             object-oriented programming toolkit. In late 2020, I read a bit about
532             L<Corrina|https://github.com/Ovid/Cor/wiki> and immediatly wanted to restart and
533             experiment my old C<Art::World> project. While searching for something somewhat
534             close to Corrina, since Corrina was only a draft and RFC, I discovered the
535             Zydeco toolkit by Toby Inkster and immediatly felt very enthusiastic to use it
536             to implement my idea. I hope it is a decent example of the possibilities this
537             wonderful framework make possible.
538              
539             It is possible that this toolkit may be used by an art management software as it
540             could be needed in an art galery or a museum.
541              
542             =head1 ROLES
543              
544             =head2 Abstraction
545              
546             This is were all kind of weird phenomenons between abstract artistic entities happen. See the
547             L<Manual|Art::World::Manual> about how it works.
548              
549             Each time an entity got an idea, it's added to the "imagination". Note there is
550             also an Idea class.
551              
552             =head2 Active
553              
554             Is used to dissociate behaviors belonging to performers as opposed to the
555             public. Provide a C<participate> method.
556              
557             =head2 Buyer
558              
559             All those behaviors and attributes are encapsulated in the C<Buyer> role because
560             there is no such thing as somebody in the art world that buy but doesn't sale.
561              
562             The C<aquire> method is requiring some C<money>. The C<money> is provided by the
563             C<Market> role.
564              
565             $collector->acquire( $artwork );
566              
567             Those behaviors are delegated to the C<change_owner()> method, and to
568             the C<pay()> method from the C<Market> role.
569              
570             When a C<Collector> C<acquire()> an C<Artwork>, the C<Artwork> C<ArrayRef> of
571             owners is automatically cleared and substituted by the new owner(s).
572             C<acquire()> will remove the value of the C<Artwork> from the owner's money.
573              
574             $artwork->change_owner( $self );
575              
576             When the paiement occurs, the money is allocated to all the artwork owners
577             involved and removed from the buyer's fortune.
578              
579             $self->pay( $artwork );
580              
581             It delegate the payment to the C<pay()> method of the C<Market> role. If the
582             payment is provided by an individual C<Buyer>, only one payment is done an the
583             money is dispatched to all the sellers. If a C<Collective> buy the good, each
584             member procede to a paiement from the C<Co-investors> point of view.
585              
586             =head2 Collectionable
587              
588             The C<collectionnable> provide a series of attributes for the ownership and
589             collectionability of artworks.
590              
591             If it's collectionable, it can go to a C<Collector> collection or in a
592             C<Museum>. A collectionable item is automatically owned by it's creator.
593              
594             C<Collectionable> provides a C<change_owner()> multi method that accepts either
595             C<Collectors> or C<Coinvestors> as an unique parameter. It takes care of setting
596             appropriately the new artwork owners and delegate the removal of the item from
597             the seller's collection.
598              
599             A private methode, C<$remove_from_seller_collection> is also available to take
600             care of the removal of the I<to-be-sold> C<Artwork> in the seller collection.
601             Since those can be owned by many persons, and that C<Artists> can own their own
602             artworks, but for now cannot be collectors, they are excluded from this
603             treatment.
604              
605             =head2 Collective
606              
607             They do stuff together. You know, art is not about lonely C<Artists> in their
608             C<Workshop>.
609              
610             This has first been designed for collectors, but could be used to
611             activate any kind of collective behavior.
612              
613             This is quite a problem because what if a group of people wants to buy? We have
614             a C<Coinvestor> class implementing the C<Collective> role that provide a
615             I<collective-acquirement> method.
616              
617             It's C<acquire()> multi method provide a way to collectively buy an item by
618             overriding the C<Buyer> role method. C<Coinvestor> is a class
619             inheriting from C<Collector> that implement the C<Collective> role so it would
620             be able to collectively acquire C<Works>.
621              
622             Note that the signatures are different between C<Buyer> and C<Collective> roles:
623              
624             $collector->acquire( $artwork );
625             # ==> using the method from the Buyer role
626              
627             $coinvestors->acquire({ art => $artwork, collective => $coinvestors });
628             # ==> using the method from the Collective role
629              
630             Just pass a self-reference to the coinvestor object and they will be able to organize and buy together.
631              
632             =head2 Event
633              
634             All the necessary attributes and methodes for having fun between Art::world's Agents.
635              
636             =head2 Exhibit
637              
638             Role for L<C<Places>|Art::World/"Place"> that display some L<C<Artworks>|Art::World/"Artwork">.
639              
640             =head2 Fame
641              
642             C<Fame> role provide ways to control the aura and reputation that various
643             C<Agents>, C<Places> or C<Works> have. Cannot be negative.
644              
645             It has an handy C<bump_fame()> method that I<self-bump> the fame count. It can
646             be used in three specific maneers:
647              
648             =over 2
649              
650             =item pass a C<PositiveNum>
651              
652             The fame will go higher
653              
654             =item pass a C<NegativeNum>
655              
656             The fame he fame will go lower
657              
658             =item no parameter
659              
660             In that case the value defined by C<< $self->config->{ FAME }->{ DEFAULT_BUMP } >>
661             will be used to increase the reputation.
662              
663             =back
664              
665             my $artist = Art::World->new_artist(
666             reputation => 0.42,
667             name => 'Questular Rontok'
668             );
669              
670             say $artist->bump_fame; # ==> 1.42
671             say $artist->bump_fame( 0.0042 ); # ==> 1.4242
672              
673             If you try to update the fame to a negative value, nothing happens and a nice
674             warning is displayed.
675              
676             The fame can be consummed by pretty much everything. A C<Place> or and C<Agent>
677             have a fame through it's reputation, and an C<Artwork> too through it's
678             aura.
679              
680             Classes that consume C<Fame> can have two different kind of attributes for
681             storing the C<Fame>:
682              
683             =over 2
684              
685             =item aura
686              
687             For C<Works> only.
688              
689             =item reputation
690              
691             For C<Agents>, C<Places>, etc.
692              
693             =back
694              
695             =head2 Identity
696              
697             Provide C<id> and a C<name> attributes.
698              
699             =head2 Invitation
700              
701             =head2 Language
702              
703             Useful when criticizing art or participating to all kind of events, especially
704             fo networking.
705              
706             =head2 Manager
707              
708             A role for those who I<take care> of exhibitions and other organizational
709             matters. See how being a C<Manager> influence an C<Agent> in the L<CLASSES>
710             section.
711              
712             =head2 Market
713              
714             It is all about offer, demand and C<money>. It is possible that a day, the
715             discourse that some people have can influence the C<Market>.
716              
717             It provide a C<pay()> method that can be used by entities consumming this role
718             to exchange artworks on the market. This method accept an C<Artwork> as an and a
719             Collector as parameters. It smartly find how many people bought the good
720             and to how many sellers the money should be dispatched.
721              
722             =head2 Showable
723              
724             Only an object that does the C<Showable> role can be exhibited. An object should
725             be exhibited only if it reached the C<Showable> stage.
726              
727             =head2 Space
728              
729             Could limit the number of person attending an event for example
730              
731             =head2 Underground
732              
733             Provide an C<experiment()> method.
734              
735             =head2 Writing
736              
737             This is much more than small talk.
738              
739             =head1 CLASSES
740              
741             =head2 Agent
742              
743             They are the activists of the Art World, previously known as the I<Wildlife>.
744              
745             my $agent = Art::World->new_agent(
746             id => 1,
747             name => Art::World::Util->new_person->fake_name,
748             reputation => 10 # Would default to zero if none specified
749             );
750              
751             $agent->participate; # ==> "That's interesting"
752              
753             A generic entity that can be any activist of the C<Art::World>. Provides all
754             kind of C<Agent> classes and roles.
755              
756             The C<Agent> got an a C<networking( $people )> method that makes possible to
757             leverage it's C<relationships>. When it is passed and C<ArrayRef> of various implementation
758             classes of C<Agents> (C<Artist>, C<Curator>, etc.) it bumps the C<reputation>
759             attributes of all of 1/10 of the C<Agent> with the highest reputation. If this
760             reputation is less than 1, it is rounded to the C<< $self->config->{ FAME }->{
761             DEFAULT_BUMP } >> constant.
762              
763             The bump coefficient can be adjusted in the configuration through C<< { FAME }->{
764             BUMP_COEFFICIENT } >>.
765              
766             There is also a special way of bumping fame when C<Manager>s are in a Networking
767             activity: The C<influence()> method makes possible to apply the special
768             C<< $self->config->{ FAME }->{ MANAGER_BUMP } >> constant. Then the C<Agent>s
769             reputations are bumped by the C<MANAGER_BUMP> value multiplicated by the highest
770             networking C<Manager> reputation. This is what the C<influence()> method
771             returns:
772              
773             return $self->config->{ FAME }->{ MANAGER_BUMP } * $reputation;
774              
775             The default values can be edited in C<art.conf>.
776              
777             =head2 Art
778              
779             Will be what you decide it to be depending on how you combine all the entities.
780              
781             This is where we are waiting to receive some I<unexpected parameters>: in other
782             words, an C<INI> file can be provided.
783              
784             =head2 Article
785              
786             Something in a C<Magazine> of C<Website> about C<Art>, C<Exhibitions>, etc.
787              
788             =head2 Artist
789              
790             In the beginning of their carreer they are usually underground and produce
791             experimental art, but this can change in time.
792              
793             my $artist = Art::World->new_artist(
794             name => 'Andy Cassrol',
795             );
796              
797             say $artist->is_homogenic;
798             #==> false
799              
800              
801             After getting collected, artists become homogenic.
802              
803             $artist->is_underground if not $artist->has_collectors;
804              
805             The artist got a lots of wonderful powers:
806              
807             =over
808              
809             =item C<create>
810              
811             When the basic abstractions of Art are articulated, a creation occurs. It
812             doesn't mean that it will create an C<Artwork>, because it requires the
813             intervention of other C<Agents>. The C<Artist> creates through a work concept.
814             This articulation can group the different attributes of the C<Abstraction> role:
815             C<discourse>, C<imagination>, C<idea>, C<process>, C<project> and C<time>.
816              
817             =item C<have_idea>
818              
819             All day long
820              
821             =back
822              
823             =head2 Artwork
824              
825             The base thing producted by artists. Artwork is subclass of
826             L<C<Work>|Art::World#Work> that have a C<Showable> and C<Collectionable> role.
827             They are usually considered as goods by the C<Market> but are also subject of
828             appreciation by the C<Public>. A lot of C<Event> happen around them.
829              
830             The C<collectionable> role provide their C<value> while they have their own
831             attributes for C<material> and C<size>. The later limits the amount of atworks
832             that can be put in a C<Place>'s space during an C<Event>.
833              
834             =head2 Book
835              
836             Where a lot of theory is written by C<Critics>
837              
838             =head2 Coinvestor
839              
840             C<Coinvestor> extend the C<Collector> class by providing an arrayref attribute
841             of C<members> through the C<Collective> role. This role makes also possible to
842             invest in artworks I<collectively>.
843              
844             =head2 Collector
845              
846             A C<Collector> is mostly an C<Agent> that consume the C<Buyer> and C<Market>
847             roles and that have a C<collection> attribute.
848              
849             my $collector = Art::World
850             ->new_collector(
851             name => Art::World::Util->new_person->fake_name,
852             money => 10_000,
853             id => 4 );
854              
855             my $artwork = Art::World
856             ->new_artwork(
857             creator => $artist ,
858             title => 'Destroy capitalism',
859             value => 9_999 );
860              
861             $collector->acquire( $artwork ),
862              
863             say $collector->money;
864             #==> 1
865              
866             say $_->title for ( $collector->collection->@* );
867             #==> Destroy capitalism
868              
869             =head2 Concept
870              
871             C<Concept> is an abstract class that does the C<Abstraction> role. It should be
872             extended but cannot be instanciated.
873              
874             =head2 Critic
875              
876             =head2 Curator
877              
878             A special kind of Agent that I<can> select Artworks, define a thematic, setup
879             everything in the space and write a catalog. They mostly do C<Exhibition>.
880              
881             =head2 Director
882              
883             =head2 Exhibition
884              
885             An C<Event> that is organised by a C<Curator>.
886              
887             my $exhibition = Art::World->new_exhibition(
888             curator => [ $curator ],
889             title => $title,
890             creator => [ $curator ]);
891              
892             =head2 Gallerist
893              
894             Director of a Gallery
895              
896             =head2 Gallery
897              
898             Just another kind of L<C<Place>|Art::World/"Place">, mostly commercial.
899              
900             Since it implements the L<C<Buyer>|Art::World/"Buyer"> role, a gallery can both
901             C<acquire()> and C<sell()>.
902              
903             Major place for C<Agent->networking> activities. Always check it's C<space>
904             though!
905              
906             =head2 Idea
907              
908             When some abstractions starts to become something in the mind of an C<Agent>.
909              
910             my $art_concept = Art::World->new_idea(
911             discourse => 'I have idead. Too many ideas. I store them in a file.',
912             imagination => [ $another_concept, $weird_idea ],
913             idea => 'idea',
914             name => 'Yet Another Idea',
915             process => [],
916             project => 'My project',
917             time => 5,
918             );
919              
920             =head2 Institution
921              
922             A C<Place> that came out of the C<Underground>.
923              
924             =head2 Magazine
925              
926             =head2 Museum
927              
928             Yet another kind of C<Place>, an institution with a lot of L<C<Artworks>|Art::World/"Artwork"> in the basement.
929              
930             =head2 Opening
931              
932             An C<Event> where you can consume free treats and speak with other networkers
933             from the art world.
934              
935             my $t = Art::World::Util->new_time( source => '2020-02-16T08:18:43' );
936             my $opening_event = Art::World->new_opening(
937             place => $place,
938             datetime => $t->datetime,
939             name => 'Come See Our Stuff',
940             smalltalk => $chat,
941             treat => [ 'Red wine', 'White wine', 'Peanuts', 'Candies' ]);
942              
943             =head2 Place
944              
945             A C<Place> must C<invite()> all kind of C<Agents> that produce C<Work> or other kind
946             of valuable social interactions. Depending of the total C<reputation> of the
947             C<Place> it will determine it's C<underground> status: when going out of the
948             C<underground>, it will become an institution.
949              
950             =head2 Playground
951              
952             A generic space where C<Art::World> C<Agents> can do all kind of weird things.
953              
954             =head2 Public
955              
956             They participate and visit events.
957              
958             =head2 School
959              
960             =head2 Sex
961              
962             =head2 Squat
963              
964             A place were art world agents are doing things. A squat that is not underground
965             anymore become an institution.
966              
967             =head2 Theory
968              
969             When some abstract concept turns to some said or written stuff.
970              
971             =head2 Website
972              
973             =head2 Work
974              
975             There are not only C<Artworks>. All C<Agent>s produce various kind of work or
976             help consuming or implementing C<Art>.
977              
978             It got an C<aura> attribute, see the L<C<Fame>|Art::World/"Fame"> about it or
979             read about L<Walter
980             Benjamin|https://en.wikipedia.org/wiki/Walter_Benjamin#%22The_Work_of_Art_in_the_Age_of_Mechanical_Reproduction%22>.
981              
982             =head2 Workshop
983              
984             A specific kind of L<C<Playground>|Art::World/"Playground"> where you can build things tranquilly.
985              
986             =head1 AUTHOR
987              
988             Sébastien Feugère <sebastien@feugere.net>
989              
990             =head1 ACKNOWLEDGEMENTS
991              
992             Thanks to everyone who has contributed to ack in any way, including Adrien
993             Lucca, Toby Inkster, Ezgi Göç, Pierre Aubert, Seb. Hu-Rillettes, Joseph Balicki,
994             Nicolas Herubel and Nadia Boursin-Piraud.
995              
996             This project was made possible by the greatness of the L<Zydeco|https://zydeco.toby.ink/> toolkit.
997              
998             =head1 COPYRIGHT AND LICENSE
999              
1000             Copyright 2006-2021 Sebastien Feugère
1001              
1002             This library is free software; you can redistribute it and/or modify it under
1003             the Artistic License 2.0.