Skip to content

Commit 37907c7

Browse files
committed
migrated to microdown. Now the project should be fully be redone because I have latex errors I do not get
1 parent 7b492f0 commit 37907c7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5185
-434
lines changed

Chapters/BeaconAndSatellite/BeaconAndSatellite.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## Beacons and Satellites @ch:beaconIn this chapter you will build a simulator for beacons and satellites. Beacons are in the sea and collect data and from time to time they should synchronise with satelittes to send data. In reality, satelittes broadcast signals and beacons are polling at regular interval for signals, then once they know that they are in range based on the first signal, a communication is established and data is exchanged.In the simulator we will present how we can implement communication between losely coupled objects. You will build step by step different variations around the observer/observable idiom. This idiom is important since it is used in Model-View-Controller and Self addressed stamped enveloppe \(S.A.S.E\) patterns. Beacons will register to satellites and when the satelittes are in range they will notify the beacons interested in the notification. ### Description![Beacons and Satelittes.](figures/Beacons.png width=70&label=fig:Beacon)A beacon is inside the sea and it collects data. It is fully autonomous. After a certain period of time it migrates to the surface waiting to send the data it collected.To communicate with satelittes, a satelitte should be available, i.e., within the zone where the beacon is.A satellite is moving around earth at a certain speed and ranging a portion of sea. It can only communicate with beacons within such range.The system is fully dynamic in the sense that new beacons may be added or removed.Satelittes may be present or not.### A simple model```Object subclass: #Satelitte
2+
instanceVariableNames: 'observers'
3+
classVariableNames: ''
4+
package: 'SatelitteAndBeacon'``````Satelitte >> initialize
5+
observers := OrderedCollection new``````Object subclass: #Beacon
6+
instanceVariableNames: 'data'
7+
classVariableNames: ''
8+
package: 'SatelitteAndBeacon'```### V1: Simple observer / observableWe start with a simple schema where beacons - register to satellites and- when the satelittes are in range they notify the beacons that registered.#### RegistrationA beacon register to a satellite as follows:```Satelitte >> register: aBeacon
9+
self addObserver: aBeacon```#### Notification```Satelitte >> position: aPoint
10+
position := aPoint.
11+
self notify``````Satelitte >> notify
12+
observers do: [ :aBeacon | aBeacon salelittePositionChanged: self ]```### V1 Implementation???### V2: AnalysisThis first implementation has several drawbacks.- One of the problem is that the message is hardcoded. - Second Imagine that the satellite should emit different notification for its position, protocol to be used, frequency.... and each kind of beacon can register for the notification kinds that fits it. We must have a list of each kind of observed property.### V2: Introducing events```Satelitte >> register: aBeacon forEvent: aEventClass
13+
aSatelitte1 addObserver: aBeacon1 with: aEventClass``````Satelitte >> addObserver: anObserver with: anEventClass
14+
observerDict at: anEventClass iAbsentPut: [OrderedCollection new].
15+
(observerDict at: anEventClass) add: anObserver``````Satelitte >> position: aPoint
16+
position := aPoint.
17+
self notify: (PositionChanged with: self)``````Satelitte >> notify: anEvent
18+
(observersDict at: anEvent class) ifPresent: [ :aBeaconList |
19+
aBeaconList do: [:aBeacon| anEvent fireOn: aBeacon ]```#### Implementation```Object subclass: #SBEvent
20+
instanceVariableNames: 'observable'
21+
classVariableNames: ''
22+
package: 'SatelitteAndBeacon'``````SBEvent subclass: #SBPositionChanged
23+
instanceVariableNames: ''
24+
classVariableNames: ''
25+
package: 'SatelitteAndBeacon'``````SBEvent subclass: #SBProtocolChanged
26+
instanceVariableNames: ''
27+
classVariableNames: ''
28+
package: 'SatelitteAndBeacon'``````SBPositionChanged >> fireOn: anObserver
29+
anObserver salelittePositionChanged: observable``````SBProtocolChanged >> fireOn: anObserver
30+
anObserver salelitteProtocolChanged: observable```#### V2 analysisAdvantages- we reuse the same mechanism for different kind of observable properties.Drawbacks- One event means that the message is also hardcoded. There is tight dependencies between the event type and the kind of behavior that is available on the observer side. ### V3 Specifying the messageNow the observer can specify the message that it wants to receive. ```aSatelitte1 when: SBPositionChanged send: #readyForHandShakeWith: to: aBeacon1``````aSatelitte1 when: SBProtocolChanged send: #useProtocol: to: aBeacon1``````Satelitte >> when: anEventClass send: aSelector to: anObserver
31+
observerDict at: anEventClass iAbsentPut: [OrderedCollection new].
32+
(observerDict at: anEventClass) add: (aSelector -> anObserver)``````Satelitte >> position: aPoint
33+
position := aPoint.
34+
self notify: (PositionChanged with: self)``````Satelitte >> notify: anEvent
35+
(observersDict at: anEvent class) ifPresent: [ :aBeaconList |
36+
aBeaconList do: [ :aBeaconAssoc |
37+
aBeaconAssoc value perform: aBeaconAssoc key with: anEvent) ]```### V5 Factoring out the announcerThe notification and management at notification should be packaged as a separate class so that we can reuse it by just delegating to it. ```Object subclass: #BSAnnouncement
38+
instanceVariableNames: 'selector observer'``````Object subclass: #BSAnnouncer
39+
instanceVariableNames: 'observerDict'``````BSAnnouncer >> when: anEventClass send: aSelector to: anObserver
40+
observerDict at: anEventClass iAbsentPut: [ OrderedCollection new] .
41+
(observerDict at: anEventClass) add:
42+
(BSAnnouncement send: aSelector to: anObserver)``````BSAnnouncer >> notify: anEvent
43+
(observersDict at: anEvent class) ifPresent: [ :aBeaconList |
44+
aBeaconList do: [ :anAnnouncement |
45+
anAnnouncement observer
46+
perform: anAnnouncement selector
47+
with: anEvent) ]``````Satelitte >> notify: anEvent
48+
self announcer notify: anEvent``````Satelitte >> when: anEventClass send: aSelector to: anObserver
49+
self announcer when: anEventClass send: aSelector to: anObserver```### Discussion about lookup of events

Chapters/Captcha/Captcha.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
## Fun with Capchas \(not used for now\)Capchas are ways to control that a service is not accessed by a robot. In this chapter we propose to implement some capchas as a way to practice and learn Pharo. Several capcha will be implemented but first let us start with just manipulating strings.## Reversing a stringThe problem that we propose to you is to reserve a string. It can be useful to build capcha as we will show later and it is a small and simple one that we will teach how to interact with strings and with collections of objects. ```'frog'
2+
->
3+
'grof'```### Solution #4There are several solutions to this problem and we will look at some of them but first let's look at some basic elements about strings.### Basic on stringsA string is a sequence of characters and the first one has the index 1 \(and not zero like in some other languages\)```'frog' size
4+
--> 4```To access an element we use the message `at: anIndex`.```'frog' at: 1
5+
-> $f```To set the value of a string element we use the message `at:anIndex put: aCharacter````| s |
6+
s := 'frog'.
7+
s at: 1 put: $z.
8+
s
9+
-> zrog```### ReversingNow to reverse the string 'frog' we see that the `$f` index 1 should be put in the position 4, the `$r` index 2 in the position 3, the `$o` index 3 in the position 2 and `$g` index 4 should be put in the position 1. We should find a relation between the actual index of the character and its future index once the string will be reversed. Let us think again about it by now using the original string size \(i.e., 4\). It seems that the target index is `size + 1 - source index`. Let us verify this hypothesis: `$f` whose index is 1, will be put in the index `4 + 1 - 1 = 4`, the `$r` whose index is 2, will be put in the position `4 + 1 - 2 = 3`, the `$o` whose index is 3, will be put in the position ` 4 + 1 - 3 = 2` and `$g` index 4 should be put in the position 1. To solve this problem we also need to know how to perform a loop. The following script prints all the number from 1 to 10. ```1 to: 10 do: [:i | Transcript show: i printString; cr].```The following script prints each element of the string 'frog' one after the other. ```1
10+
to: 'frog' size
11+
do: [ :i | Transcript show: ('frog' at: i) ; cr ]``````| sourceString targetString |
12+
sourceString := 'frog'.
13+
targetString := String new: sourceString size.
14+
15+
1 to: targetString size do: [ :i |
16+
targetString at: (sourceString size + 1) - i put: (sourceString at: i)
17+
].
18+
targetString```Now we can define a new method on the class `String`. In such case the sourceString variable is not necessarily anymore since this is the string receiving the message that will be the sourceString. ```String>>captchaReversed
19+
20+
| targetString |
21+
targetString := String new: self size.
22+
23+
1 to: targetString size do: [ :i |
24+
targetString at: (self size + 1) - i put: (self at: i)
25+
].
26+
^ targetString``````'youpi' captchaReversed
27+
-> 'ipuoy'``` Now `self size + 1` is invariant during the loop. It does not change so we can extract it outside the loop.```String>>captchaReversed
28+
29+
| targetString n |
30+
targetString := String new: self size.
31+
n := (self size + 1).
32+
1 to: targetString size do: [ :i |
33+
targetString at: n - i put: (self at: i)
34+
].
35+
^ targetString
36+
]]]
37+
38+
Now looking at how it is implemented in Pharo we see the following definition defined in the superclass of ==String==.
39+
40+
41+
[[[
42+
SequenceableCollection>>reversed
43+
"Answer a copy of the receiver with element order reversed."
44+
"Example: 'frog' reversed"
45+
46+
| n result src |
47+
n := self size.
48+
result := self species new: n.
49+
src := n + 1.
50+
1 to: n do: [:i | result at: i put: (self at: (src := src - 1))].
51+
^ result``` `self species new: n.` makes the code working on several different collection. `species` returns a class of the same species than the receiver of the message, the class `Array` if the receiver is an array, the String class if the receiver a string. So result points on a new string or collection.## PalindromsThe following example brings an interesting idea for another string manipulation for captcha: asking the user to enter an palindrome. Palindrome are words or sentences which are symmetrical. For example, 'civic', 'refer' and 'No lemon, no melon' are palidromes.```'civic' captchaReversed
52+
->
53+
'civic'```Here is a way to check if a string is a capcha.```captchaIsAnagram
54+
"Returns true whether the receiver is an anagram.
55+
'anna' captchaIsAnagram
56+
true
57+
'andna' captchaIsAnagram
58+
true
59+
'avdna' captchaIsAnagram
60+
false
61+
"
62+
1
63+
to: self size//2
64+
do: [ :i | (self at: i) = (self at: self size + 1 - i)
65+
ifFalse: [ ^false ]
66+
].
67+
^true```Now again the expression `self size + 1` is constant. ```captchaIsAnagram
68+
"Returns true whether the receiver is an anagram.
69+
'anna' captchaIsAnagram
70+
true
71+
'andna' captchaIsAnagram
72+
true
73+
'avdna' captchaIsAnagram
74+
false
75+
"
76+
| n |
77+
n := self size + 1.
78+
1
79+
to: self size//2
80+
do: [ :i |
81+
( self at: i ) = ( self at: n - i)
82+
ifFalse: [ ^false ]
83+
].
84+
^true```% Local Variables:% eval: (flyspell-mode -1)% End:

0 commit comments

Comments
 (0)