Skip to content

Commit

Permalink
migrated to microdown. Now the project should be fully be redone beca…
Browse files Browse the repository at this point in the history
…use I have latex errors I do not get
  • Loading branch information
Ducasse committed Mar 18, 2023
1 parent 7b492f0 commit 37907c7
Show file tree
Hide file tree
Showing 49 changed files with 5,185 additions and 434 deletions.
49 changes: 49 additions & 0 deletions Chapters/BeaconAndSatellite/BeaconAndSatellite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## 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
instanceVariableNames: 'observers'
classVariableNames: ''
package: 'SatelitteAndBeacon'``````Satelitte >> initialize
observers := OrderedCollection new``````Object subclass: #Beacon
instanceVariableNames: 'data'
classVariableNames: ''
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
self addObserver: aBeacon```#### Notification```Satelitte >> position: aPoint
position := aPoint.
self notify``````Satelitte >> notify
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
aSatelitte1 addObserver: aBeacon1 with: aEventClass``````Satelitte >> addObserver: anObserver with: anEventClass
observerDict at: anEventClass iAbsentPut: [OrderedCollection new].
(observerDict at: anEventClass) add: anObserver``````Satelitte >> position: aPoint
position := aPoint.
self notify: (PositionChanged with: self)``````Satelitte >> notify: anEvent
(observersDict at: anEvent class) ifPresent: [ :aBeaconList |
aBeaconList do: [:aBeacon| anEvent fireOn: aBeacon ]```#### Implementation```Object subclass: #SBEvent
instanceVariableNames: 'observable'
classVariableNames: ''
package: 'SatelitteAndBeacon'``````SBEvent subclass: #SBPositionChanged
instanceVariableNames: ''
classVariableNames: ''
package: 'SatelitteAndBeacon'``````SBEvent subclass: #SBProtocolChanged
instanceVariableNames: ''
classVariableNames: ''
package: 'SatelitteAndBeacon'``````SBPositionChanged >> fireOn: anObserver
anObserver salelittePositionChanged: observable``````SBProtocolChanged >> fireOn: anObserver
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
observerDict at: anEventClass iAbsentPut: [OrderedCollection new].
(observerDict at: anEventClass) add: (aSelector -> anObserver)``````Satelitte >> position: aPoint
position := aPoint.
self notify: (PositionChanged with: self)``````Satelitte >> notify: anEvent
(observersDict at: anEvent class) ifPresent: [ :aBeaconList |
aBeaconList do: [ :aBeaconAssoc |
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
instanceVariableNames: 'selector observer'``````Object subclass: #BSAnnouncer
instanceVariableNames: 'observerDict'``````BSAnnouncer >> when: anEventClass send: aSelector to: anObserver
observerDict at: anEventClass iAbsentPut: [ OrderedCollection new] .
(observerDict at: anEventClass) add:
(BSAnnouncement send: aSelector to: anObserver)``````BSAnnouncer >> notify: anEvent
(observersDict at: anEvent class) ifPresent: [ :aBeaconList |
aBeaconList do: [ :anAnnouncement |
anAnnouncement observer
perform: anAnnouncement selector
with: anEvent) ]``````Satelitte >> notify: anEvent
self announcer notify: anEvent``````Satelitte >> when: anEventClass send: aSelector to: anObserver
self announcer when: anEventClass send: aSelector to: anObserver```### Discussion about lookup of events
Expand Down
84 changes: 84 additions & 0 deletions Chapters/Captcha/Captcha.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## 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'
->
'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```To access an element we use the message `at: anIndex`.```'frog' at: 1
-> $f```To set the value of a string element we use the message `at:anIndex put: aCharacter````| s |
s := 'frog'.
s at: 1 put: $z.
s
-> 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
to: 'frog' size
do: [ :i | Transcript show: ('frog' at: i) ; cr ]``````| sourceString targetString |
sourceString := 'frog'.
targetString := String new: sourceString size.

1 to: targetString size do: [ :i |
targetString at: (sourceString size + 1) - i put: (sourceString at: i)
].
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

| targetString |
targetString := String new: self size.

1 to: targetString size do: [ :i |
targetString at: (self size + 1) - i put: (self at: i)
].
^ targetString``````'youpi' captchaReversed
-> 'ipuoy'``` Now `self size + 1` is invariant during the loop. It does not change so we can extract it outside the loop.```String>>captchaReversed

| targetString n |
targetString := String new: self size.
n := (self size + 1).
1 to: targetString size do: [ :i |
targetString at: n - i put: (self at: i)
].
^ targetString
]]]

Now looking at how it is implemented in Pharo we see the following definition defined in the superclass of ==String==.


[[[
SequenceableCollection>>reversed
"Answer a copy of the receiver with element order reversed."
"Example: 'frog' reversed"

| n result src |
n := self size.
result := self species new: n.
src := n + 1.
1 to: n do: [:i | result at: i put: (self at: (src := src - 1))].
^ 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
->
'civic'```Here is a way to check if a string is a capcha.```captchaIsAnagram
"Returns true whether the receiver is an anagram.
'anna' captchaIsAnagram
true
'andna' captchaIsAnagram
true
'avdna' captchaIsAnagram
false
"
1
to: self size//2
do: [ :i | (self at: i) = (self at: self size + 1 - i)
ifFalse: [ ^false ]
].
^true```Now again the expression `self size + 1` is constant. ```captchaIsAnagram
"Returns true whether the receiver is an anagram.
'anna' captchaIsAnagram
true
'andna' captchaIsAnagram
true
'avdna' captchaIsAnagram
false
"
| n |
n := self size + 1.
1
to: self size//2
do: [ :i |
( self at: i ) = ( self at: n - i)
ifFalse: [ ^false ]
].
^true```% Local Variables:% eval: (flyspell-mode -1)% End:
Expand Down
Loading

0 comments on commit 37907c7

Please sign in to comment.