Wanneer een bestand over het Internet verstuurd wordt, dan wordt het aan de kant van de verzender eerst door een splitter opgedeeld in kleinere segmenten. Die segmenten worden pakketten genoemd. Alle pakketten worden daarna individueel over het Internet verstuurd naar dezelfde ontvanger. Als de ontvanger alle pakketten van het bestand heeft ontvangen, dan gebruikt hij een assembler om het originele bestand te reconstrueren.

splitter/assembler
Schematische voorstelling van het splitsen en assembleren van boodschappen die over het Internet verstuurd worden.

Het Internet gebruikt packet switching1 om de route van de pakketten doorheen het netwerk te bepalen. Daarbij is het vaak wenselijk dat de pakketten van hetzelfde bestand verschillende routes volgen om opstopping te voorkomen. Als gevolg daarvan bereiken die pakketten de ontvanger niet noodzakelijk in hun originele volgorde.

packet switching
Een geanimeerde demonstratie die aantoont hoe datapakketten over het Internet verstuurd worden (packet switching).

Bovendien is het Internet niet feilloos en gebeurt het wel eens dat pakketten hun bestemming nooit of pas zeer laat bereiken.

Opgave

In deze opgave moet je een klasse Assembler implementeren die boodschappen kan reconstrueren op basis van binnengekomen pakketten. Bij het aanmaken van objecten van de klasse Assembler moet de locatie van een tekstbestand doorgegeven worden dat alle binnengekomen pakketten bevat. Zo een tekstbestand ziet er bijvoorbeeld als volgt uit:

6220    1   10  Because he's the hero Gotham deserves, 
6220    9   10   
5181    5   7   in time, like tears in rain. Time to die.
6220    3   10  So we'll hunt him. 
6220    5   10  Because he's not a hero. 
5181    6   7    
5181    2   7   shoulder of Orion. I watched C-beams 
5181    4   7   Gate. All those moments will be lost 
6220    6   10  He's a silent guardian. 
5181    3   7   glitter in the dark near the Tannhäuser 
6220    7   10  A watchful protector. 
5181    1   7   believe. Attack ships on fire off the 
6220    0   10  We have to chase him. 
5181    0   7   I've seen things you people wouldn't 
6220    4   10  Because he can take it. 
6220    2   10  but not the one it needs right now. 
6220    8   10  A Dark Knight. 

Elke regel van het tekstbestand stelt één enkel pakket voor en bestaat uit vier informatievelden die van elkaar gescheiden worden door tabs:

  1. unieke code $$m \in \mathbb{N}$$ van de boodschap waaruit het pakket komt

  2. volgnummer $$i \in \mathbb{N}$$ van het pakket; bij het opdelen van een boodschap worden pakketten opeenvolgend genummerd: het eerste pakket heeft volgnummer 0 en het laatste pakket heeft volgnummer $$p - 1$$

  3. aantal pakketten $$p \in \mathbb{N}_0$$ waarin de boodschap werd opgedeeld

  4. tekstfragment (string) dat zelf geen tabs bevat

De pakketten van eenzelfde boodschap komen in willekeurige volgorde voor en het tekstbestand moet niet noodzakelijk alle pakketten van die boodschap bevatten. Hetzelfde pakket komt echter nooit meerdere keren voor. De klasse Assembler moet minstens de volgende methoden ondersteunen:

Voorbeeld

Bij onderstaande voorbeeldsessie gaan we ervan uit dat de tesktbestanden pakketten_01.txt2 en pakketten_02.txt3 zich in de huidige directory bevinden.

>>> assembler = Assembler('pakketten_01.txt')
>>> assembler.isVolledig(6220)
True
>>> assembler.isVolledig(5181)
True
>>> assembler.isVolledig(1234)
False
>>> assembler.volledigeBoodschappen()
{6220, 5181}
>>> assembler.onvolledigeBoodschappen()
{}
>>> print(assembler.boodschap(6220))
0. We have to chase him.
1. Because he's the hero Gotham deserves,
2. but not the one it needs right now.
3. So we'll hunt him.
4. Because he can take it.
5. Because he's not a hero.
6. He's a silent guardian.
7. A watchful protector.
8. A Dark Knight.
9. 
>>> print(assembler.boodschap(5181))
0. I've seen things you people wouldn't
1. believe. Attack ships on fire off the
2. shoulder of Orion. I watched C-beams
3. glitter in the dark near the Tannhäuser
4. Gate. All those moments will be lost
5. in time, like tears in rain. Time to die.
6. 
>>> assembler.boodschap(1234)
Traceback (most recent call last):
AssertionError: onvolledige boodschap

>>> assembler = Assembler('pakketten_02.txt')
>>> assembler.isVolledig(2997)
True
>>> assembler.isVolledig(1938)
False
>>> assembler.isVolledig(1234)
False
>>> assembler.volledigeBoodschappen()
{9949, 6450, 7469, 2997}
>>> assembler.onvolledigeBoodschappen()
{1938: (13, 17)}
>>> print(assembler.boodschap(2997))
0. Did you ever hear the tragedy of Darth
1. Plagueis the Wise? I thought not. It's not a
2. story the Jedi would tell you. It's a Sith
3. legend. Darth Plagueis was a Dark Lord of the
4. Sith so powerful and so wise, he could use the
5. Force to influence the midichlorians to
6. create life...He had such a knowledge of the
7. dark side that he could even keep the once he
8. cared about from dying. The dark side of the
9. Force is a pathway to many abilities some
10. consider to be unnatural. He became so
11. powerful...The only thing he was afraid of was
12. losing his power. Which eventually, of course,
13. he did. Unfortunately, he taught his
14. apprentice everything he knew, then his
15. apprentice killed him in his sleep. Ironic,
16. he could have others from death, but not
17. himself.
18. 
>>> assembler.boodschap(1938)
Traceback (most recent call last):
AssertionError: onvolledige boodschap
>>> assembler.boodschap(1234)
Traceback (most recent call last):
AssertionError: onvolledige boodschap