Corona virus simulator

General FreeBASIC programming questions.
ShawnLG
Posts: 136
Joined: Dec 25, 2008 20:21

Corona virus simulator

Postby ShawnLG » Mar 23, 2020 17:17

I have written a small program that shows how the corona virus spreads from person to person from close contact. This does not take on real world simulation of the corona virus. This would be very difficult to program. Way too many variables and situations would need to be considered.

[Updated Mar 25, 2020:]
Now includes "Shelter-in-place" which shows how effective it is on mitigating the spread of the virus.

[Updated Apr 14, 2020:]
Added max & min travel distance from home. This will remove nomadic movement and simulate communal movement.
Added vacation (long distance travel). This has a huge effect on the virus's long term survival. It can escape from heard immunity.
Added hashing for much faster O time complexity for infection search.

CoronaSim.bas

Code: Select all

'Corona virus (COVID 19) simulator v1.1 by Shawn Grieb

Const WHITE = RGB(255,255,255)
Const GREEN = RGB(0,255,0)
Const RED =  RGB(255,0,0)
Const YELLOW = RGB(200,200,0)
Const GREY = RGB(175,175,175)
Const DARKGREY = RGB(100,100,100)
Const HEALTHY = 0
Const INFECTED = 1
Const IMMUNED = 2
Const DEAD = 3
Const MOBILE = 0
Const STAYATHOME = 1

'Hash settings
Const HASHSTACKSIZE = 10
Const HASHMULTIPLYER = 5

'User modifiable constants.
Const NUMOFPEOPLE = 20000
Const SCREENX = 1280
Const SCREENY = 720
Const DEATHRATE = 0.034   'Percent of people who die from complications of the virus. Define in decimal form.
Const SHELTERINPLACE = .25'Percent of people who shelter in place. Define in decimal form.
Const INFDURATION = 500   'Infection duration.
Const IMMDURATION = 5000  'Immunity duration.
Const MAXDISTANCE = 15    'The max distance the most adventurous persons will travel from home. (This is not vacation travel)
Const MINDISTANCE = 10    'The minimum distance to define nonadventurous homebodies.
Const TRAVELDELAYRATE = 5 'Number of program iterations before one person vacation travels (long distance) to a new random point and make it their new home base.

Type person
   Dim As Integer homex 'Homex and homey is the person's home base or center of their area of travel in their community.
   Dim As Integer homey 'Homex and homey will make the random walk non-nomadic.
   Dim As Integer distance 'How far from home the person travels or how adventurous they are.
   Dim As Integer x 'X and Y are current position on map
   Dim As Integer y
   Dim As Integer healthstate
   Dim As Integer mobilestate
   Dim As Integer durationcount
End Type

'StashTable, the hashing of stacked bins.
type StashTable
    declare Constructor(tsize as Integer, stackdepth As integer)
    declare destructor()
    declare sub push(xkey As Integer, ykey As Integer, id As Integer)
    Declare Function setstackdump(xkey As Integer, ykey As Integer) As Integer
    Declare Function pop() As Integer
    Declare Sub reset()
    private:
    dim as Integer Ptr Ptr sht
    Dim As Integer Ptr tx
    Dim As Integer Ptr ty
    Dim As Integer Ptr si
    Dim as Integer tablesize
    Dim As Integer stacksize
    Dim As Integer popstackindex
    Dim As LongInt poptableindex
End type

constructor StashTable(dimsize as Integer, stackdepth As integer)
    this.sht = new Integer Ptr [dimsize+1]
    this.tx = New Integer [dimsize+1]
    this.ty = New Integer [dimsize+1]
    this.si = New Integer [dimsize+1]
    For i As Integer = 0 To dimsize
       this.sht[i] = New Integer [stackdepth+1]
       this.tx[i] = -1
       this.si[i] = 0
    Next i
    this.tablesize = dimsize
    this.stacksize = stackdepth
    this.popstackindex = -1
    this.poptableindex = -1
End constructor

destructor StashTable()
     For i As Integer = 0 To this.tablesize
        Delete [] This.sht[i]
     Next i
    Delete [] this.sht
    Delete this.tx
    Delete this.ty
    Delete This.si
End destructor
 
sub StashTable.push(xkey As Integer, ykey As Integer, idkey As Integer)
    dim as LongInt index = (xkey * ykey) mod this.tablesize
    dim as Integer hashcount = 0
    Do
       If This.tx[index] = -1 Then
          this.tx[index] = xkey
          this.ty[index] = ykey
       EndIf
       'push key in valid index
       If this.tx[index] = xkey And this.ty[index] = ykey Then
          If this.si[index] < this.stacksize Then
             this.sht[index][this.si[index]] = idkey
             this.si[index] = this.si[index] + 1
             Exit Do
          Else
             Print "Push stack overflow!"
             Sleep
             exit Do
          EndIf
       Else
          index = (index + 1) mod this.tablesize
           if hashcount > this.tablesize Then
              print "Push hash falure!"
              Sleep
           end If
           hashcount = hashcount + 1
       EndIf
    loop
end Sub

function StashTable.setstackdump(xkey As Integer, ykey As Integer) As Integer
   Dim As LongInt index = (xkey * ykey) Mod this.tablesize
   Dim as Integer hashcount = 0
    Do
       If this.tx[index] = -1 Then
          Return 0
        ElseIf This.tx[index] = xkey And this.ty[index] = ykey Then
           this.poptableindex = index
           this.popstackindex = This.si[index] - 1
           Return -1
        Else
           index = (index + 1) mod this.tablesize
           if hashcount > this.tablesize Then
              print "Setstackdump hash falure!"
              Sleep
           end If
           hashcount = hashcount + 1
        EndIf 
    Loop
End Function

Function StashTable.pop() As Integer
   Dim As Integer popkey = -1
   If this.poptableindex > -1 Then
      popkey = this.sht[this.poptableindex][this.popstackindex]
      this.popstackindex = this.popstackindex - 1
      If this.popstackindex = -1 Then
         this.poptableindex = -1
      EndIf
   End If
   Return popkey
End Function

Sub StashTable.reset()
   For t As Integer = 0 To This.tablesize
       this.tx[t] = -1
       this.si[t] = 0
    Next t
    this.popstackindex = -1
    this.poptableindex = -1
End Sub

Dim As stashtable hash = stashtable(NUMOFPEOPLE * HASHMULTIPLYER, HASHSTACKSIZE)

ScreenRes SCREENX, SCREENY, 32,,0
Dim As Any Ptr backbuffer, mapbuffer
backbuffer = ImageCreate(SCREENX,SCREENY,,32)
mapbuffer = ImageCreate(SCREENX,SCREENY,,32)
Dim As Integer travelstate = 0
Dim As person Ptr p
p = New person [NUMOFPEOPLE+1]

For i As Integer = 1 To NUMOFPEOPLE
   p[i].homex = SCREENX * Rnd
   p[i].homey = SCREENY * Rnd
   p[i].x = p[i].homex
   p[i].y = p[i].homey
   p[i].distance = (MAXDISTANCE-MINDISTANCE) * Rnd + MINDISTANCE
   p[i].healthstate = HEALTHY
   P[i].mobilestate = MOBILE
   If Rnd < SHELTERINPLACE Then p[i].mobilestate = STAYATHOME
   p[i].durationcount = 0
Next
p[1].healthstate = INFECTED 'Start with one person infected.

Do
   Dim As Integer direction
   hash.reset()
   For i As Integer = 1 To NUMOFPEOPLE
       If p[i].healthstate <> DEAD Then
          If p[i].mobilestate = MOBILE Then
             direction = 5 * Rnd
             Select Case direction
             Case 1'left
                If p[i].x > 1 Then
                   If p[i].x > p[i].homex - p[i].distance Then
                      p[i].x = p[i].x - 1
                   End If
                EndIf
             Case 2'right
                If P[i].x < SCREENX-1 Then
                   If p[i].x < p[i].homex + p[i].distance Then
                       p[i].x = p[i].x + 1
                    End If
                EndIf
             Case 3'up
                If p[i].y > 1 Then
                   If p[i].y > p[i].homey - p[i].distance Then
                      p[i].y = p[i].y - 1
                   End If
                EndIf
             Case 4'down
                If p[i].y < SCREENY-1 Then
                   If p[i].y < p[i].homey + p[i].distance Then
                      p[i].y = p[i].y + 1
                   End If
                EndIf
             End Select
          End If
       End If
       hash.push(p[i].x, p[i].y, i)
   Next i
   For i As Integer = 1 To NUMOFPEOPLE
       'Check for nebors and infect them.
       If p[i].healthstate = INFECTED Then
          If hash.setstackdump(p[i].x, p[i].y) Then
             Dim As Integer index
             Do      
                index = hash.pop()
                If index > -1 Then
                   If p[index].healthstate = HEALTHY Then
                      p[index].healthstate = INFECTED
                   End If
                Else
                   Exit Do
                End If
             Loop
          EndIf
       End If
       'Check infected statecount.
       If p[i].healthstate = INFECTED Then
          If p[i].durationcount < INFDURATION Then
             p[i].durationcount = p[i].durationcount + 1
          Else
             If Rnd < DEATHRATE Then
                p[i].healthstate = DEAD
                p[i].durationcount = 0
             Else
                p[i].healthstate = IMMUNED
                p[i].durationcount = 0
             EndIf
          EndIf
       EndIf
       'Check immuned statecount.
       If p[i].healthstate = IMMUNED Then
          If p[i].durationcount < IMMDURATION Then
             p[i].durationcount = p[i].durationcount + 1
          Else
             p[i].healthstate = HEALTHY
             p[i].durationcount = 0
          EndIf
       EndIf
   Next
   Line backbuffer, (0,0)-(SCREENX-1,SCREENY-1),0,BF'cls
   
   'Move one person for long distance travel. (move or vacation)
   If travelstate = 0 Then
      Dim As Integer index = (Rnd * NUMOFPEOPLE+1)-1 'Pick a person at random.
      If p[index].healthstate <> DEAD Then 'The dead do not go on vacation.
         Dim As Integer oldx = p[index].x
         Dim As Integer oldy = p[index].y
         Dim As Integer newx = Rnd * SCREENX
         Dim As Integer newy = Rnd * SCREENY
         p[index].homex = newx
         p[index].homey = newy
         p[index].x = p[index].homex
         p[index].y = p[index].homey
         'Draw travel vector.
         Line backbuffer, (newx,newy)-(oldx,oldy),GREY
      End If
   End If
   travelstate = (travelstate + 1) Mod TRAVELDELAYRATE
   'Draw persons and stats.
   Dim As Integer healthycount = 0, infectedcount = 0, immunedcount = 0, deadcount = 0
   
   For i As Integer = 1 To NUMOFPEOPLE
      Dim As Integer x = p[i].x, y = p[i].y
      Dim As Long c
      Select Case p[i].healthstate
      Case HEALTHY
         c = GREEN
         healthycount = healthycount + 1
      Case INFECTED
         c = RED
         infectedcount = infectedcount + 1
      Case IMMUNED
         c = YELLOW
         immunedcount = immunedcount + 1
      case DEAD
         c = WHITE
         deadcount = deadcount + 1
      End Select
      PSet backbuffer, (x,y),c
   Next
   Draw String backbuffer, (SCREENX/2 -48, 0), "(Corona Sim v1.1)", WHITE,, PSet
   Draw String backbuffer, (0, 0), "Healthy:  "+Str(healthycount), GREEN,, PSet
   Draw String backbuffer, (0, 9), "Infected: "+Str(infectedcount), RED,, PSet
   Draw String backbuffer, (0, 19), "Immuned:  "+Str(immunedcount), YELLOW,, PSet
   Draw String backbuffer, (0, 29), "Dead:     "+Str(deadcount), GREY,, PSet
   Draw String backbuffer, (SCREENX-180,0), "Shelter-In-Place: "+Str(SHELTERINPLACE*100)+"%", GREY,, PSet
   Draw String backbuffer, (SCREENX-180,9), "Death Rate: "+Str(DEATHRATE*100)+"%", GREY,, PSet
   ScreenLock
   Put (0,0),backbuffer,PSet
   ScreenUnLock
   Sleep 1
Loop Until InKey <> ""
ImageDestroy(backbuffer)
ImageDestroy(mapbuffer)
Delete [] p
Last edited by ShawnLG on Apr 14, 2020 16:24, edited 2 times in total.
jj2007
Posts: 1523
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Corona virus simulator

Postby jj2007 » Mar 24, 2020 1:49

Very cute, thumbs up!
srvaldez
Posts: 2464
Joined: Sep 25, 2005 21:54

Re: Corona virus simulator

Postby srvaldez » Mar 24, 2020 12:01

see https://www.washingtonpost.com/graphics ... simulator/
Richard Russel author of bbc Basic wrote a nice version in bbc Basic, but their Forum is down so I can't post a link
deltarho[1859]
Posts: 2530
Joined: Jan 02, 2017 0:34
Location: UK

Re: Corona virus simulator

Postby deltarho[1859] » Mar 24, 2020 12:36

Without Randomize: 166 dead

Five runs with Randomize: 196, 150, 151, 174, 184 dead

With Randomize and many more runs will give us a potential upper bound on deaths; that is a worst-case scenario.

With more than 30 runs we can then use the normal distribution to calculate confidence limits on the expected number of deaths.
grindstone
Posts: 737
Joined: May 05, 2015 5:35
Location: Germany

Re: Corona virus simulator

Postby grindstone » Mar 24, 2020 13:59

Nice work!
bluatigro
Posts: 651
Joined: Apr 25, 2012 10:35
Location: netherlands

Re: Corona virus simulator

Postby bluatigro » Mar 25, 2020 6:30

look also to my version :
'virus outbreak sim'
UEZ
Posts: 586
Joined: May 05, 2017 19:59
Location: Germany

Re: Corona virus simulator

Postby UEZ » Mar 25, 2020 18:32

@ShawnLG: well done but the move of the pixels are too turbulent imho...

Here my contribution as I don't want to create another topic:

Code: Select all

'Coded by UEZ build 2020-04-02
#include "string.bi"

#Define _Dist(x1, x2, y1, y2)   (((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)))
#Define _Round(x)             ((x + 0.5) Shr 0)
#Define Ceiling(x)            (-((-(x) * 2.0 - 0.5) Shr 1))
#Define Map(a, b, c)         (a / b * c)

Const iW = 1024, iH = 768, iPeople = 19999, iPSize = 1, iMaxSickDays = 14, fDaySpeed = 0.0075, iDayInoFound = 60, probDeath = 0.05, infProb = 0.25, gH = 100

Type vZone
   Dim As Ushort x1, y1, x2, y2
   Dim As Uinteger pp(iPeople + 1) 'index of people
   Dim As Ulong c
End Type

Declare Sub Motion()
Declare Function RandomRange(fStart As Single, fEnd As Single) As Single
Declare Sub CreateGridZones(Zones() As vZone, iZones As Ushort, imgw As Ushort, imgh As Ushort)

Const As ULong  iBGColor = &hFF000000

ScreenRes iW, iH, 32, 2, 100
ScreenSet 1, 0

Dim Shared As Any Ptr img, img_clr
img = Imagecreate(iW, iH, &hFF404040, 32)
img_clr = Imagecreate(iW, iH - gH, iBGColor, 32)

Randomize , 2

Dim Shared As Uinteger iPSize2, iPrevDaysPassed = 0
iPSize2 = iPSize^2
Dim Shared As Single fDaysPassed = 0
Type vPeople
   Dim As Single x, y, vx, vy, sickdays, healthydays
   Dim As Ulong c
   Dim As Ubyte status, zone 'status: healthy = 0, infected = 1, cured = 2, dead = 3, inoculated = 4
End Type

Dim Shared As Ushort p0, iGridZones = 12^2
Dim Shared As vZone GridZone(iGridZones)
Dim As Uinteger i, j

CreateGridZones(GridZone(), iGridZones, iW, iH - gH)

iGridZones -= 1
For j = 0 To iGridZones 'create color for each grid zone for debugging purpose
   GridZone(j).c = &h80000000 Or Culng(Rnd() * &hFFFFFF)
Next
   
Dim Shared As vPeople People(iPeople)
For i = 0 To iPeople
   People(i).x = RandomRange(iPSize + 1, iW - iPSize - 1)
   People(i).y = RandomRange(iPSize + 1, iH - iPSize - gH - 1)
   People(i).c = &hFFFFFFFF
   People(i).vx = 0.15 * Rnd() - 0.075
   People(i).vy = 0.15 * Rnd() - 0.075
   People(i).status = 0
   People(i).sickdays = 0
   People(i).healthydays = 0
Next
p0 = Cuint(Rnd * iPeople) 'gunman aka patient zero
People(p0).c = &hFFFF0000
People(p0).status = 1
'People(p0).vx *= 5
'People(p0).vy *= 4

Dim As Ulong iFPS = 0, iFPS_current = 0
Dim As Double fTimer = Timer

Do
   Put img, (0, 0), img_clr, Pset
   Motion()
   Put (0, 0), img, Pset
   Draw String(1, 1), iFPS_current & " fps", Rgba(&hF0, &hF0, &h10, &hFF)
   Flip
   fDaysPassed += fDaySpeed
   If Timer - fTimer > 0.99 Then
      iFPS_current = iFPS
      iFPS = 0
      fTimer = Timer
   Else
      iFPS += 1
   End If
    Sleep 1, 1
Loop Until Len(InKey())

Imagedestroy(img_clr)
Imagedestroy(img)

Sub Motion()
   Dim As Uinteger i, j, k, l, iBucket, index, iHealthy = 0, iInfected = 0, iCured = 0, iDead = 0, iInoculated = 0
   Static As Single cr = 0
   Dim As Single t1, t2
   For j = 0 To iGridZones 'reset amount if people in the bucket
      GridZone(j).pp(0) = 0
      'Line img, (GridZone(j).x1, GridZone(j).y1)-(GridZone(j).x2, GridZone(j).y2), GridZone(j).c, BF 'display GridZone for debugging
   Next
   For i = 0 To iPeople
      'move each people if not dead
      If People(i).status <> 3 Then 'skip dead people
         People(i).x += People(i).vx
         People(i).y += People(i).vy
      End If
      'check border collision
      If People(i).x < 0 Or People(i).x > iW - iPSize - 1 Then People(i).vx *= -1
      If People(i).y < 0 Or People(i).y > iH - iPSize - gh - 1 Then People(i).vy *= -1
      'group people into GridZone for more efficient collision check afterwards
      For j = 0 To iGridZones
         If People(i).x > GridZone(j).x1 And People(i).x < GridZone(j).x2 - iPSize And People(i).y > GridZone(j).y1 And People(i).y < GridZone(j).y2 - iPSize Then
            GridZone(j).pp(0) += 1
            GridZone(j).pp(GridZone(j).pp(0)) = i
            'People(i).c = GridZone(j).c
            People(i).zone = j
            Exit For
         End If
      Next
      
      If fDaysPassed > 7 And People(i).status = 0 And Rnd() < 0.000000075 Then
         If People(i).status = 0 Then People(i).status = 1 'make random people sick. People came back from infected country
      End If
      
      If People(i).status = 0 Then People(i).healthydays += fDaySpeed
      
      If People(i).healthydays > iDayInoFound And People(i).status = 0 Then 'immunisation has been found -> inoculation started
         If Rnd() < 0.0015 Then People(i).status = 4 'add a delay as not each people will be incoculated at the same time
      End If
      
      If People(i).sickdays > iMaxSickDays Then
         People(i).sickdays = 0
         If Rnd() < probDeath Then 'probability of death at 5%
            People(i).status = 3
            People(i).vx = 0
            People(i).vy = 0
         Else 'cured
            People(i).status = 2
         End If
      End If
      
      Select Case People(i).status
         Case 0
            iHealthy += 1
         Case 1
            People(i).sickdays += fDaySpeed
            iInfected += 1
            If i = p0 Then   'show patient zero with a circle during infection phase and color flash
               People(p0).c = &hFF000000 Or (cr Shl 16)
               cr += 10
               t1 = iPSize / 2
               'Circle img, (People(i).x + t1, People(i).y + t1), 2 * iPSize, &hFFC0C000
            Else
               People(i).c = &hFFF00000
            End If
         Case 2
            iCured += 1
            People(i).c = &hFF00F000
         Case 3
            iDead += 1
            People(i).c = &hFFE238EC
         Case 4
            iInoculated += 1
            People(i).c = &hFF2020FF
      End Select

      Line img, (People(i).x, People(i).y)-(People(i).x + iPSize, People(i).y + iPSize), People(i).c, BF
   Next
   
   'collision check of infected peoples
   For i = 0 To iPeople      
      If People(i).status = 1 Then 'don't check dead and healty peoples      
         iBucket = GridZone(People(i).zone).pp(0)
         For j = 1 To iBucket
            index = GridZone(People(i).zone).pp(j)
            If People(index).status = 0 And index <> i Then
               If Int(_Dist(People(i).x, People(index).x, People(i).y, People(index).y)) <= iPSize2 And Rnd() > infProb Then 'infect people by 75% probability
                  People(index).status = 1
                  
                  'increase the speed of infection
                  'People(index).vx *= -1
                  'People(index).vy *= -1
                  
                  'decrease the speed of infection -> infected people will move reverse direction on infection
                  'People(i).vx *= -1
                  'People(i).vy *= -1
               End If
            End If
         Next
      End If
   Next
   Dim As Ushort iSum = iHealthy + iCured + iInoculated
   Windowtitle("Corona Infection Simulation by UEZ / h: " & iSum & ", inf: " & iInfected & Format(iInfected / (iPeople - iDead), " (0.00%)") & _
            ", c: " & iCured & ", d: " & iDead & Format(iDead / (iPeople + 1), " (0.00%)") & _
            ", ino: " & iInoculated & ", day: " & Format(fDaysPassed, "#"))
            
   Static As Single posx = 0
   If posx <= iW Then
      If Cushort(fDaysPassed) Mod 7 = 0 And fDaysPassed > 1 And iPrevDaysPassed < Cushort(fDaysPassed) Then
         Line img, (posx, iH - gH)-(posx, iH), &hFF000000
         iPrevDaysPassed = fDaysPassed
         'posx += 1
      Else
         t2 = gH / (iPeople + 1)
         Line img, (posx, iH)-(posx, iH - (iHealthy * t2)), &h40FFFFFF
         Line img, (posx, iH)-(posx, iH - (iInfected * t2)), &h40FF0000
         If iDead Then Line img, (posx, iH)-(posx, iH - (iDead * t2)), &hF0E238EC
         If iCured Then Line img, (posx, iH - gH)-(posx, iH - gH + (iCured * t2)), &h4000F000
         If iInoculated Then Line img, (posx, iH - gH)-(posx, iH - gH + (iInoculated * t2)), &hF02020FF
      End If
      posx += fDaySpeed * 10
   End If
End Sub

'Original code by Neptilo @ https://math.stackexchange.com/questions/466198/algorithm-to-get-the-maximum-size-of-n-squares-that-fit-into-a-rectangle-with-a
'Modified by UEZ
Sub CreateGridZones(Zones() As vZone, iZones As Ushort, imgw As Ushort, imgh As Ushort)
   Dim As Single ratio = Iif(Frac(Sqr(iZones)) = 0, 1, Iif(imgw >= imgh, imgw / imgh, imgh / imgw))
   Dim As Single ncols_float = Sqr(iZones * ratio), nrows_float = iZones / ncols_float
   
   'Find best option filling the whole height
   Dim As Uinteger nrows1 = Ceiling(nrows_float), ncols1 = Ceiling(iZones / nrows1)
   While nrows1 * ratio < ncols1
      nrows1 += 1
      ncols1 = Ceiling(iZones / nrows1)
   Wend
   Dim As Single cell_size1 = imgh / nrows1
   
   'Find best option filling the whole width
   Dim As Uinteger ncols2 = Ceiling(ncols_float), nrows2 = Ceiling(iZones / ncols2)
   While ncols2 < nrows2 * ratio
      ncols2 += 1
      nrows2 = Ceiling(iZones / ncols2)
   Wend
   Dim As Single cell_size2 = imgw / ncols2

   'Find the best values
   Dim As Uinteger nrows, ncols
   If cell_size1 < cell_size2 Then
      nrows = nrows1
      ncols = ncols1
   Else
      nrows = nrows2
      ncols = ncols2
   End If
   
   Dim As Uinteger i,j, k, x, y
   Dim As Integer dz = iZones - (nrows * ncols), bz = Iif(dz <> 0, 1, 0)
   Dim As Single dx = imgw / ncols, dy = imgh / nrows
   
   For j = 0 To nrows - 1 - bz
      For i = 0 To ncols - 1
         x = Cuint(i * dx)
         Zones(k).x1 = x
         Zones(k).x2 = x + dx
         Zones(k).y1 = (j Mod nrows) * dy
         Zones(k).y2 = Zones(k).y1 + dy
         k += 1
      Next
   Next
   
   If bz Then
      ncols = iZones - k
      dx = imgw / ncols
      For i = 0 To ncols - 1
         x = Cuint(i * dx)
         Zones(k).x1 = x
         Zones(k).x2 = x + dx
         Zones(k).y1 = (j Mod nrows) * dy
         Zones(k).y2 = Zones(k).y1 + dy
         k += 1
      Next
   End If
End Sub


Function RandomRange(fStart As Single, fEnd As Single) As Single
   Return Rnd() * (fEnd - fStart) + fStart
End Function

Runs fasted on my system when using -gen gcc -O 3 -s gui in x64 mode.

White: normal healthy
Red: infected
Green: cured
Purple: dead
Blue: inoculated

Image

Edit1: added inoculation
Edit2: small code optimizations (thanks badidea for the suggestions)
Edit3: small code optimizations (thanks badidea for the suggestions)
Edit4: increased zone size -> now much better performance. Be careful when changing the amount of zones!
Edit5: added random source of infection to simulate people travel and some other things
Edit6: added a graph at the bottom
Last edited by UEZ on Apr 02, 2020 7:14, edited 12 times in total.
badidea
Posts: 2079
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Corona virus simulator

Postby badidea » Mar 25, 2020 19:34

UEZ wrote:@ShawnLG: well done but the move of the pixels are too turbulent imho...

No 'Herd immunity' 100% infection rate.
UEZ
Posts: 586
Joined: May 05, 2017 19:59
Location: Germany

Re: Corona virus simulator

Postby UEZ » Mar 25, 2020 19:47

badidea wrote:
UEZ wrote:@ShawnLG: well done but the move of the pixels are too turbulent imho...

No 'Herd immunity' 100% infection rate.


Currently no immunization has been found...^^
badidea
Posts: 2079
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Corona virus simulator

Postby badidea » Mar 25, 2020 20:47

UEZ wrote:
badidea wrote:No 'Herd immunity' 100% infection rate.

Currently no immunization has been found...^^

I think your "R0 (basic reproduction number)" is too high (https://en.wikipedia.org/wiki/Herd_immunity). For the corona-virus R0 is not known very accurate yet (see table). With these 'social distancing' why try to bring this number below 1 (for now).
How many others does one ill person infect (on average) in the beginning of your simulation?
This 'gunman' infects hundreds when he gets a large speed. Looks like a zombie apocalypse.

Concerning code this:
If Particles(index).status <> 1 And Particles(index).status <> 2 And Particles(index).status <> 3 And index <> i Then
Can be:
If Particles(index).status = 0 And index <> i Then
I think?

And I would use an enum:
enum E_STATUS
ST_INIT '0
ST_INFEC '1
ST_CURED '2
ST_DEAD '3
end enum

And I think that fPSizeHalf can be left out in:
If Int(_Dist(Particles(i).x + fPSizeHalf, Particles(index).x + fPSizeHalf, _
Particles(i).y + fPSizeHalf, Particles(index).y + fPSizeHalf)) <= iPSize Then
Because Dist_() does (x2 - x1) and (y2 - y1) so fPSizeHalf disappears.

To further speed-up the simulation, Sqr() is not needed, you can compared against iPSize ^ 2, which is a constant (9).

To make it more realistic, one could reduce the speed of the infected, e.g. by half. And hope that they don't get on to an air-plane to the other side of the map.

With this modified code, you see that some never get infected:

Code: Select all

'Coded by UEZ build 2020-03-25 (modified by badidea)
#include "string.bi"

'#Define _Dist(x1, x2, y1, y2)   (Sqr((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)))
#Define _DistSq(x1, x2, y1, y2)   ((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1))

Declare Sub Motion()
Declare Function RandomRange(fStart As Single, fEnd As Single) As Single

Const As UShort iW = 1024, iH = 768
Const As ULong  iBGColor = &hFF000000

ScreenRes iW, iH, 32, 2
ScreenSet 1, 0

Dim Shared As Any Ptr img, img_clr
img = Imagecreate(iW, iH, 0, 32)
img_clr = Imagecreate(iW, iH, iBGColor, 32)

Randomize , 2

const As Uinteger iParticles = 4999, iPSize = 3
const As Single fPSizeHalf = iPSize / 2
const as single minInfecDist = iPSize * iPSize

enum E_STATUS
   ST_INIT
   ST_INFEC
   ST_CURED
   ST_DEAD
end enum

Type vParticle
   Dim As Single x, y, vx, vy, days
   Dim As Ulong c
   Dim As Ubyte status, zone 'status: alife = 0, infected = 1, cured = 2, dead = 3
End Type

Type vZone
   Dim As Ushort x1, y1, x2, y2
   Dim As Uinteger pp(5000) 'index of particle
   Dim As Ulong c
End Type

Dim Shared As vZone Zones(3)
Dim As Uinteger i, j

'left upper
Zones(0).x1 = 0
Zones(0).y1 = 0
Zones(0).x2 = iW / 2
Zones(0).y2 = iH / 2
Zones(0).pp(0) = 0
Zones(0).c = &hFFFF8080

'right upper
Zones(1).x1 = iW / 2
Zones(1).y1 = 0
Zones(1).x2 = iW
Zones(1).y2 = iH / 2
Zones(1).pp(0) = 0
Zones(1).c = &hFF80FF80

'left bottom
Zones(2).x1 = 0
Zones(2).y1 = iH / 2
Zones(2).x2 = iW / 2
Zones(2).y2 = iH
Zones(2).pp(0) = 0
Zones(2).c = &hFF8080FF

'right bottom
Zones(3).x1 = iW / 2
Zones(3).y1 = iH / 2
Zones(3).x2 = iW
Zones(3).y2 = iH
Zones(3).pp(0) = 0
Zones(3).c = &hFFFFFFFF

Dim Shared As vParticle Particles(iParticles)
For i = 0 To iParticles
   Particles(i).x = RandomRange(iPSize + 1, iW - iPSize - 1)
   Particles(i).y = RandomRange(iPSize + 1, iH - iPSize - 1)
   Particles(i).c = &hFFFFFFFF
   Particles(i).vx = 0.5 * Rnd() - 0.25
   Particles(i).vy = 0.5 * Rnd() - 0.25
   Particles(i).status = ST_INIT
   Particles(i).days = 0
Next
i = Cuint(Rnd * iParticles) 'gunman
Particles(i).c = &hFFFF0000
Particles(i).status = ST_INFEC
Particles(i).vx *= 0.5 '5
Particles(i).vy *= 0.4 '4

Dim As Ulong iFPS = 0, iFPS_current = 0
Dim As Double fTimer = Timer

Do
   Put img, (0, 0), img_clr, Pset
   Motion()
   Put (0, 0), img, Pset
   Draw String(1, 1), iFPS_current & " fps", Rgba(&hF0, &hF0, &h10, &hFF)
   Flip
   If Timer - fTimer > 0.99 Then
      iFPS_current = iFPS
      iFPS = 0
      fTimer = Timer
   Else
      iFPS += 1
   End If
    Sleep 1, 1
Loop Until Len(InKey())

Imagedestroy(img_clr)
Imagedestroy(img)

Sub Motion()
   Dim As Uinteger i, j, k, l, iBucket, index, iAlive = 0, iInfected = 0, iCured = 0, iDead = 0
   For j = 0 To 3 'reset amount if pixel in the bucket
      Zones(j).pp(0) = 0
   Next
   For i = 0 To iParticles
      'move each pixel if not dead
      If Particles(i).status <> ST_DEAD Then
         Particles(i).x += Particles(i).vx
         Particles(i).y += Particles(i).vy
      End If
      'check border collision
      If Particles(i).x < 0 Or Particles(i).x > iW - iPSize - 1 Then Particles(i).vx *= -1
      If Particles(i).y < 0 Or Particles(i).y > iH - iPSize - 1 Then Particles(i).vy *= -1
      'group pixel into zones for collision check afterwards
      For j = 0 To 3
         If Particles(i).x > Zones(j).x1 And Particles(i).x < Zones(j).x2 - iPSize And Particles(i).y > Zones(j).y1 And Particles(i).y < Zones(j).y2 - iPSize Then
            Zones(j).pp(0) += 1
            Zones(j).pp(Zones(j).pp(0)) = i
            'Particles(i).c = Zones(j).c
            Particles(i).zone = j
            Exit For
         End If
      Next
     
      If Particles(i).days > 14 Then
         Particles(i).days = 0
         If Rnd() < 0.05 Then 'dead
            Particles(i).status = ST_DEAD
            Particles(i).vx = 0
            Particles(i).vy = 0
         Else 'cured
            Particles(i).status = ST_CURED
            'back to normal speed
            Particles(i).vx *= 2
            Particles(i).vy *= 2
         End If
      End If
      Select Case Particles(i).status
         Case ST_INIT
            iAlive += 1
            Particles(i).c = &hFFFFFFFF
         Case ST_INFEC
            Particles(i).days += 0.0075
            iInfected += 1
            Particles(i).c = &hFFF00000
         Case ST_CURED
            iCured += 1
            Particles(i).c = &hFF00F000
         Case ST_DEAD
            iDead += 1
            Particles(i).c = &hFFE238EC
      End Select
      Line img, (Particles(i).x, Particles(i).y)-(Particles(i).x + iPSize, Particles(i).y + iPSize), Particles(i).c, BF
   Next
   'collision check of infected pixels
   For i = 0 To iParticles     
      If Particles(i).status = ST_INFEC Then       
         If Particles(i).status <> ST_DEAD Then
            iBucket = Zones(Particles(i).zone).pp(0)
            For j = 1 To iBucket
               index = Zones(Particles(i).zone).pp(j)
               If Particles(index).status = ST_INIT And index <> i Then
                  If Int(_DistSq(Particles(i).x, Particles(index).x, Particles(i).y, Particles(index).y)) <= minInfecDist Then
                     Particles(index).status = ST_INFEC
                     Particles(index).vx *= 0.5
                     Particles(index).vy *= 0.5
                  End If
               End If
            Next
         End If
      End If
   Next
   Windowtitle("Corona Infection Simulation / alive: " & 1 + iParticles - iDead & ", infected: " & iInfected & ", cured: " & iCured & ", dead: " & iDead & Format(iDead / (iParticles + 1), " (0.00%)"))
End Sub

Function RandomRange(fStart As Single, fEnd As Single) As Single
   Return Rnd() * (fEnd - fStart) + fStart
End Function

Edit: ST_ALIVE changed to ST_INIT
Last edited by badidea on Mar 25, 2020 22:04, edited 2 times in total.
UEZ
Posts: 586
Joined: May 05, 2017 19:59
Location: Germany

Re: Corona virus simulator

Postby UEZ » Mar 25, 2020 22:00

@badidead: thanks for having a closer look to the code.

Some of your code suggestions I had already made. But to avoid Sqr was a good hint.

Well, my target was not create a realistic simulation with all possibilities and parameters because I don't have deep knowledge about the science behind. This is more a pseudo simulation to see some pixels moving around.
I added extra the "gunman" to spread the virus faster to the public...^^

Btw, I've updated the code above.
badidea
Posts: 2079
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Corona virus simulator

Postby badidea » Mar 25, 2020 22:30

UEZ wrote:Btw, I've updated the code above.

One more thing, you have:

Code: Select all

  If Particles(i).status = 1 Then       
         If Particles(i).status <> 3 And Particles(i).status <> 4 Then 'don't check dead and healty pixels
But status the status is 0,1,2, or 3
So this can be reduced to just:

Code: Select all

  If Particles(i).status = 1 Then
I think?

What does alive mean in your code? This alive include infected and cured?
UEZ
Posts: 586
Joined: May 05, 2017 19:59
Location: Germany

Re: Corona virus simulator

Postby UEZ » Mar 25, 2020 22:50

badidea wrote:
UEZ wrote:Btw, I've updated the code above.

One more thing, you have:

Code: Select all

  If Particles(i).status = 1 Then       
         If Particles(i).status <> 3 And Particles(i).status <> 4 Then 'don't check dead and healty pixels
But status the status is 0,1,2, or 3
So this can be reduced to just:

Code: Select all

  If Particles(i).status = 1 Then
I think?

What does alive mean in your code? This alive include infected and cured?


Thanks - your are right - fixed the part with unneeded checks.

Alive means not dead.^^ The pixel is infected (red) but still alive and with a probability of 5% the pixel will die. Alive = infected (not dead) + cured / inoculated.
badidea
Posts: 2079
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Corona virus simulator

Postby badidea » Mar 25, 2020 23:13

UEZ wrote:Alive means not dead.^^ The pixel is infected (red) but still alive and with a probability of 5% the pixel will die. Alive = infected (not dead) + cured / inoculated.

But this comment is confusing:
Dim As Ubyte status, zone 'status: alive = 0, infected = 1, cured = 2, dead = 3, inoculated = 4
On infection you switch form 0 to 1. So 0 must mean 'initial' or something I think.

To my 'forked' version, I added a 'day counter' and a 'infected by gunman (patient 0)' counter.
With patient 0 at the same speed as the others, he infects 10 to 25 others (depending on his actual speed and start position).

Code: Select all

dim shared as integer iGunMan, infectedbyGunMan = 0

'Coded by UEZ build 2020-03-25 (modified by badidea)
#include "string.bi"

'#Define _Dist(x1, x2, y1, y2)   (Sqr((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)))
#Define _DistSq(x1, x2, y1, y2)   ((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1))

Declare Sub Motion()
Declare Function RandomRange(fStart As Single, fEnd As Single) As Single

Const As UShort iW = 1024, iH = 768
Const As ULong  iBGColor = &hFF000000

ScreenRes iW, iH, 32, 2
width iW \ 8, iH \ 16
ScreenSet 1, 0

Dim Shared As Any Ptr img, img_clr
img = Imagecreate(iW, iH, 0, 32)
img_clr = Imagecreate(iW, iH, iBGColor, 32)

Randomize , 2

const As Uinteger iParticles = 4999, iPSize = 3
const As Single fPSizeHalf = iPSize / 2
const as single minInfecDist = iPSize * iPSize

enum E_STATUS
   ST_INIT
   ST_INFEC
   ST_CURED
   ST_DEAD
end enum

Type vParticle
   Dim As Single x, y, vx, vy, days
   Dim As Ulong c
   Dim As Ubyte status, zone 'status: alife = 0, infected = 1, cured = 2, dead = 3
End Type

Type vZone
   Dim As Ushort x1, y1, x2, y2
   Dim As Uinteger pp(5000) 'index of particle
   Dim As Ulong c
End Type

Dim Shared As vZone Zones(3)
Dim As Uinteger i, j

'left upper
Zones(0).x1 = 0
Zones(0).y1 = 0
Zones(0).x2 = iW / 2
Zones(0).y2 = iH / 2
Zones(0).pp(0) = 0
Zones(0).c = &hFFFF8080

'right upper
Zones(1).x1 = iW / 2
Zones(1).y1 = 0
Zones(1).x2 = iW
Zones(1).y2 = iH / 2
Zones(1).pp(0) = 0
Zones(1).c = &hFF80FF80

'left bottom
Zones(2).x1 = 0
Zones(2).y1 = iH / 2
Zones(2).x2 = iW / 2
Zones(2).y2 = iH
Zones(2).pp(0) = 0
Zones(2).c = &hFF8080FF

'right bottom
Zones(3).x1 = iW / 2
Zones(3).y1 = iH / 2
Zones(3).x2 = iW
Zones(3).y2 = iH
Zones(3).pp(0) = 0
Zones(3).c = &hFFFFFFFF

Dim Shared As vParticle Particles(iParticles)
For i = 0 To iParticles
   Particles(i).x = RandomRange(iPSize + 1, iW - iPSize - 1)
   Particles(i).y = RandomRange(iPSize + 1, iH - iPSize - 1)
   Particles(i).c = &hFFFFFFFF
   Particles(i).vx = 0.5 * Rnd() - 0.25
   Particles(i).vy = 0.5 * Rnd() - 0.25
   Particles(i).status = ST_INIT
   Particles(i).days = 0
Next
i = Cuint(Rnd * iParticles) 'gunman (patient 0)
Particles(i).c = &hFFFF0000
Particles(i).status = ST_INFEC
'Particles(i).vx *= 5
'Particles(i).vy *= 4
iGunMan = i

Dim As Ulong iFPS = 0, iFPS_current = 0
Dim As Double fTimer = Timer
dim as single simDays = 0

Do
   Put img, (0, 0), img_clr, Pset
   Motion()
   Put (0, 0), img, Pset
   Draw String(1, 1), iFPS_current & " fps", Rgba(&hF0, &hF0, &h10, &hFF)
   Draw String(1, 1 + 16), "simDays: " & int(simDays), Rgba(&hF0, &hF0, &h10, &hFF)
   Draw String(1, 1 + 32), "Infected by gunman: " & infectedbyGunMan , Rgba(&hF0, &hF0, &h10, &hFF)
   Flip
   If Timer - fTimer > 0.99 Then
      iFPS_current = iFPS
      iFPS = 0
      fTimer = Timer
   Else
      iFPS += 1
   End If
   simDays += 0.0075
    Sleep 1, 1
Loop Until Len(InKey())

Imagedestroy(img_clr)
Imagedestroy(img)

Sub Motion()
   Dim As Uinteger i, j, k, l, iBucket, index, iAlive = 0, iInfected = 0, iCured = 0, iDead = 0
   For j = 0 To 3 'reset amount if pixel in the bucket
      Zones(j).pp(0) = 0
   Next
   For i = 0 To iParticles
      'move each pixel if not dead
      If Particles(i).status <> ST_DEAD Then
         Particles(i).x += Particles(i).vx
         Particles(i).y += Particles(i).vy
      End If
      'check border collision
      If Particles(i).x < 0 Or Particles(i).x > iW - iPSize - 1 Then Particles(i).vx *= -1
      If Particles(i).y < 0 Or Particles(i).y > iH - iPSize - 1 Then Particles(i).vy *= -1
      'group pixel into zones for collision check afterwards
      For j = 0 To 3
         If Particles(i).x > Zones(j).x1 And Particles(i).x < Zones(j).x2 - iPSize And Particles(i).y > Zones(j).y1 And Particles(i).y < Zones(j).y2 - iPSize Then
            Zones(j).pp(0) += 1
            Zones(j).pp(Zones(j).pp(0)) = i
            'Particles(i).c = Zones(j).c
            Particles(i).zone = j
            Exit For
         End If
      Next
     
      If Particles(i).days > 14 Then
         Particles(i).days = 0
         If Rnd() < 0.05 Then 'dead
            Particles(i).status = ST_DEAD
            Particles(i).vx = 0
            Particles(i).vy = 0
         Else 'cured
            Particles(i).status = ST_CURED
            'back to normal speed
            Particles(i).vx *= 2
            Particles(i).vy *= 2
         End If
      End If
      Select Case Particles(i).status
         Case ST_INIT
            iAlive += 1
            Particles(i).c = &hFFFFFFFF
         Case ST_INFEC
            Particles(i).days += 0.0075
            iInfected += 1
            Particles(i).c = &hFFF00000
         Case ST_CURED
            iCured += 1
            Particles(i).c = &hFF00F000
         Case ST_DEAD
            iDead += 1
            Particles(i).c = &hFFE238EC
      End Select
      Line img, (Particles(i).x, Particles(i).y)-(Particles(i).x + iPSize, Particles(i).y + iPSize), Particles(i).c, BF
   Next
   'collision check of infected pixels
   For i = 0 To iParticles
      If Particles(i).status = ST_INFEC Then       
            iBucket = Zones(Particles(i).zone).pp(0)
            For j = 1 To iBucket
               index = Zones(Particles(i).zone).pp(j)
               If Particles(index).status = ST_INIT And index <> i Then
                  '(i) infects (index)?
                  If Int(_DistSq(Particles(i).x, Particles(index).x, Particles(i).y, Particles(index).y)) <= minInfecDist Then
                     Particles(index).status = ST_INFEC
                     Particles(index).vx *= 0.5
                     Particles(index).vy *= 0.5
                     if i = iGunMan then infectedbyGunMan += 1
                  End If
               End If
            Next
      End If
   Next
   Windowtitle("Corona Infection Simulation / alive: " & 1 + iParticles - iDead & ", infected: " & iInfected & ", cured: " & iCured & ", dead: " & iDead & Format(iDead / (iParticles + 1), " (0.00%)"))
End Sub

Function RandomRange(fStart As Single, fEnd As Single) As Single
   Return Rnd() * (fEnd - fStart) + fStart
End Function

Another speed optimisation is to set an end-of-sickness-date, and compare against that. So that you don't have to do Particles(i).days += 0.0075 for all infected every loop. This part could even be done 1 once every 10 loops. Currently, in simulated time, it correspond to a heath check every ~10 minutes.
dodicat
Posts: 6555
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Corona virus simulator

Postby dodicat » Mar 25, 2020 23:43

Not so much a simulation but a message.

Code: Select all

Redim As Long t()
Dim As Long x
Do
    x+=1
    Redim Preserve t(1 To x)
    Read t(x)
Loop Until t(x)=-1
Redim Preserve t(1 To Ubound(t)-1)

Type pt
    As Long x,y
    As Ulong col
    As Long idx,done
    #define range(f,l) Int(Rnd*((l+1)-(f)))+(f)
End Type

Function dist(p1 As pt,p2 As pt) As Long
    Return ( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y))
End Function

Function closest(pts() As pt,p As pt) Byref As Long
    Dim As Long dt=1000000,distance
    Static As Long res
    For n As Long=Lbound(pts) To Ubound(pts)
        If pts(n).idx=p.idx Or pts(n).done=1 Then Goto nxt
        distance=dist(pts(n),p)
        If dt> distance Then dt = distance:res=n
        nxt:
    Next n
    Return (res)
End Function

Sub shuffle(a() As pt)
    For n As Integer = Lbound(a) To Ubound(a)-1
        Swap a(n), a(range(n,Ubound(a)))
    Next n
End Sub

Dim As Integer w,h
Screen 20,32
Screeninfo w,h
Redim As pt c()
Dim As Long ctr
For x As Long=1 To w-2 Step 8
    For y As Long=1 To h-2 Step 8
        ctr+=1
        Redim Preserve c(1 To ctr)
        c(ctr)=Type(x,y,Rgb(0,200,0),ctr)
    Next y
Next x
For n As Long=Lbound(t) To Ubound(t)
    c(t(n)).done=1
Next
shuffle(c())
Dim As pt s=Type(range(1,(w-1)),range(1,(h-1)))
Dim As Long z =range(1,Ubound(c))
Dim As pt p=c(z)
Dim As Long cl,counter

Do
    counter+=1
    cl=closest(c(),p)
    p=c(cl)
    If c(cl).done=0 Then c(cl).col=Rgb(200,0,0)
    c(cl).done=1
    Screenlock
    Cls
    For n As Long=Lbound(c) To Ubound(c)
        Line(c(n).x-2,c(n).y-2)-(c(n).x+2,c(n).y+2),c(n).col,bf
    Next
   
    Screenunlock
    Sleep 1
Loop Until counter>ubound(c)
windowtitle "DONE . . ."
Sleep


Data _
523, 524, 525, 526, 527, 535, 536, 537, 538, 539, 540, 541, 542, 618, 619, _
620, 621, 622, 623, 624, 634, 635, 636, 637, 713, 714, 715, 717, 718, 719, _
720, 721, 732, 733, 808, 809, 815, 816, 817, 818, 829, 904, 911, 912, 913, _
914, 925, 1000, 1008, 1009, 1010, 1011, 1021, 1022, 1096, 1105, 1106, 1107, 1108, 1118, _
1192, 1201, 1202, 1203, 1204, 1214, 1288, 1298, 1299, 1300, 1301, 1310, 1384, 1385, 1394, _
1395, 1396, 1397, 1405, 1406, 1481, 1491, 1492, 1493, 1494, 1501, 1577, 1578, 1579, 1588, _
1589, 1590, 1591, 1592, 1595, 1596, 1597, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1684, _
1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1781, 1782, 1783, 1784, 1785, 1786, 1787, _
1880, 1881, 2159, 2254, 2255, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, _
2359, 2360, 2361, 2362, 2363, 2364, 2365, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, _
2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2538, 2539, 2540, 2541, 2542, _
2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, _
2558, 2639, 2653, 2654, 2735, 2749, 2831, 2844, 2939, 3122, 3123, 3128, 3129, 3130, 3131, _
3132, 3216, 3217, 3218, 3219, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3312, 3313, 3314, _
3315, 3319, 3320, 3323, 3324, 3325, 3326, 3407, 3408, 3414, 3415, 3420, 3421, 3422, 3503, _
3510, 3517, 3599, 3605, 3613, 3695, 3701, 3708, 3791, 3792, 3797, 3803, 3887, 3888, 3889, _
3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3984, 3985, 3986, _
3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 4082, 4083, 4084, _
4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4189, 4284, 4463, 4483, 4559, 4560, _
4578, 4579, 4580, 4655, 4656, 4657, 4658, 4674, 4675, 4676, 4751, 4752, 4753, 4754, 4755, _
4756, 4770, 4771, 4772, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4867, 4868, 4943, _
4947, 4948, 4949, 4950, 4951, 4952, 4962, 4963, 5039, 5045, 5046, 5047, 5048, 5049, 5050, _
5057, 5058, 5143, 5144, 5145, 5146, 5147, 5148, 5150, 5151, 5152, 5153, 5241, 5242, 5243, _
5244, 5245, 5246, 5337, 5338, 5339, 5340, 5431, 5432, 5433, 5519, 5524, 5525, 5526, 5527, _
5615, 5618, 5619, 5620, 5711, 5712, 5713, 5714, 5807, 5808, 5903, 6962, 6963, 6964, 6969, _
6970, 6971, 6972, 6973, 7056, 7057, 7058, 7059, 7060, 7061, 7067, 7068, 7069, 7151, 7152, _
7155, 7156, 7157, 7158, 7164, 7165, 7247, 7252, 7253, 7254, 7261, 7262, 7343, 7349, 7350, _
7351, 7358, 7439, 7445, 7446, 7447, 7448, 7454, 7535, 7542, 7543, 7544, 7549, 7550, 7631, _
7632, 7638, 7639, 7640, 7641, 7645, 7727, 7728, 7729, 7730, 7735, 7736, 7737, 7738, 7739, _
7740, 7741, 7832, 7833, 7834, 7835, 7836, 8210, 8211, 8216, 8217, 8218, 8219, 8220, 8304, _
8305, 8306, 8307, 8311, 8312, 8313, 8314, 8315, 8316, 8317, 8400, 8401, 8402, 8403, 8407, _
8408, 8411, 8412, 8413, 8414, 8495, 8496, 8502, 8503, 8508, 8509, 8510, 8591, 8598, 8605, _
8687, 8693, 8701, 8783, 8789, 8796, 8879, 8880, 8885, 8891, 8975, 8976, 8977, 8978, 8979, _
8980, 8981, 8982, 8983, 8984, 8985, 8986, 8987, 8988, 8989, 9072, 9073, 9074, 9075, 9076, _
9077, 9078, 9079, 9080, 9081, 9082, 9083, 9084, 9085, 9086, 9170, 9171, 9172, 9173, 9174, _
9175, 9176, 9177, 9178, 9179, 9180, 9181, 9277, 9372, 9647, 9743, 9839, 9852, 9853, 9930, _
9931, 9932, 9933, 9934, 9935, 9936, 9937, 9938, 9939, 9940, 9941, 9942, 9943, 9944, 9945, _
9946, 9947, 9948, 9949, 10025, 10026, 10027, 10028, 10029, 10030, 10031, 10032, 10033, 10034, 10035, _
10036, 10037, 10038, 10039, 10040, 10041, 10042, 10043, 10044, 10045, 10120, 10121, 10127, 10140, 10141, _
10223, 10311, 10319, 10407, 10415, 10503, 10504, 10599, 10600, 10601, 10696, 10697, 10698, 10707, 10708, _
10709, 10710, 10711, 10712, 10713, 10714, 10792, 10793, 10794, 10801, 10802, 10803, 10804, 10805, 10806, _
10807, 10808, 10809, 10810, 10811, 10896, 10897, 10900, 10904, 10905, 10906, 10907, 10908, 10992, 10996, _
11002, 11003, 11004, 11005, 11087, 11092, 11099, 11100, 11101, 11183, 11188, 11195, 11196, 11197, 11198, _
11279, 11284, 11292, 11293, 11294, 11375, 11376, 11380, 11388, 11389, 11390, 11471, 11472, 11473, 11476, _
11484, 11485, 11568, 11569, 11570, 11571, 11572, 11580, 11581, 11664, 11665, 11666, 11667, 11668, 11675, _
11676, 11762, 11763, 11764, 11769, 11770,-1

Return to “General”

Who is online

Users browsing this forum: No registered users and 7 guests