• Hi All

    Please note that at the Chandoo.org Forums there is Zero Tolerance to Spam

    Post Spam and you Will Be Deleted as a User

    Hui...

  • When starting a new post, to receive a quicker and more targeted answer, Please include a sample file in the initial post.

Duration of Stay V2

NicGreen

Member
Good Day All,

You may remember a few months ago I was doing a study on parking within a town. Well it went great and the coding completed by you guys worked well.

The issue now is that, that sheet worked quite well for 800 car parks but did get a little slow. However now i'll be completing a study for 3500 spaces. The sheet attached is an example of just one parking area filled with the collected data so you can imagine how big it gets when i have 80 worksheets.

Could I get this coding put into a more efficient VBA Script?
I intend to use that script for over 80 sheets so efficiency will be key.

The coding basically digests the input data (table on left) and looks for vehicles recorded more than once and calculates that into a value of time. This therefore calculates the duration of stay for a parked vehicle.

Therefore if 1 represents the vehicle being recorded and 0 being not recording the following code would represent a vehicle staying for 4 hours. (vehicles were recorded at 2hr intervals)
01100

01110 would represent a vehicle staying for 6 hours
01010 would represent a vehicle staying for 2 trips of 2 hour duration.

Etc etc.

Any issues feel free to let me know.
 

Attachments

  • Duration of Stay & Occupancy 1st July.xlsx
    36.2 KB · Views: 11
Hi, NicGreen!

Just for clarifying purposes there's no "code" in your uploaded workbook (it's a .xlsx file), just a bunch of formulas... array formulas. So it's very reasonable that with a huge amount of data the workbook turns slow.

If you're looking for a migration from formulas to macro (VBA code) it'd help a lot if you describe:
a) The workbook structure. It has only one worksheet but you mentioned 80, all with the same layout?
b) The flow of data. Which is the input (I guess that columns B:G), how and when it's updated, which output do you want (columns K:AI maybe ;)), how would you manually get this output.

Regards!
 
Yes sorry not sure why i said code. Its all formulas.
In regards to your questions.
a) Yes there will be 80 or so and they will ALL have the same layout. The only changes will be the descriptors or the area and the input table simply expands or contracts depending on how many parking spaces are within an area. Note i have uploaded a modified file showing the table which describes the parking area. The plan was to simply copy the worksheet once the VBA is sorted and change the values of the worksheet. That was it saves time on your end so you don't have to repeat yourself with each sheet.
b) the flow of data is only updated once and yes the output is K:AI as you pointed out. This output does the following:
  1. The data is entered into the input area B:G once the data is recorded. Each colour represents a different parking time restriction. I.e Red = 2 hour limit Black may equal = 4 hours. The reason I chose colours is because the parking areas may have different restrictions and by noting down what each colour represents i can then work out the overstay time (that is the time in which a vehicle stays over the limit i.e. 2 hour. Then cumulatively access all parking areas once all data is collected. It also helped a lot with the formulas.
  2. If i were to manually analyse the data. I would have to cross examine every vehicle registration to see if it was recorded again in the same parking bay. I.e. if Registration ABC123 was noted in the first recording i would manually then check the next recording interval to see if the vehicle was noted again. If so it is save to assume the vehicle has stayed there the whole time.
  3. I would then access if the vehicle was overstaying the limit. Say ABC123 was recorded twice (therefore 2Hour Stay) and the limit was 1 hour the vehicle would have overstayed by 1 hour.
I hope this helps your queries.
 

Attachments

  • Duration of Stay & Occupancy 1st July.xlsx
    169.5 KB · Views: 7
Last edited:
Hi, NicGreen!

A bit late, I forget about this. But better later than never, so give a look at the uploaded file. I did this:
- completely remove all formulas except for those of row 3 and input header totals, all set by code
- created a area table for color, allowed time(*) and default rows no.
- redefined the named ranges to make all them dynamic and worksheet scoped (so you can copy the ws)
- added two command buttons for easily processing and easy clearing
- added a 1st worksheet ("0" but you can rename it and change the code properly") that won't be processed
- added a general command button in this

The dynamic named ranges are (for worksheet 1):
AreaTable: =DESREF('1'!$A$15;;;CONTARA('1'!$A:$A)-3;3) -----> in english: =OFFSET('1'!$A$15,,,COUNTA('1'!$A:$A)-3,3)
AreaColorList: =DESREF('1'!AreaTable;;0;;1) -----> in english: =OFFSET('1'!AreaTable,,0,,1)
AreaTimeList: =DESREF('1'!AreaTable;;1;;1) -----> in english: =OFFSET('1'!AreaTable,,1,,1)
TimingList: ='1'!$C$22:$G$22
ParkingInputTable: =DESREF('1'!$B$22;;;CONTARA('1'!$B:$B)-6;COLUMNAS('1'!TimingList)) -----> in english: =OFFSET('1'!$B$22,,,COUNTA('1'!$B:$B)-6,COLUMNS('1'!TimingList))
VehicleList: =DESREF('1'!$K$4;;;CONTARA('1'!$K:$K)-2;1) -----> in english: =OFFSET('1'!$K$4,,,,COUNTA('1'!$K:$K)-2,1)
ParkingOutputTable: =DESREF('1'!$L$4;;;FILAS('1'!VehicleList);FILAS('1'!AreaTable)*(COLUMNAS('1'!TimingList)+1)) -----> in english: =OFFSET('1'!$L$4,,,ROWS('1'!VehicleList),ROWS('1'!AreaTable)*(COLUMNS('1'!TimingList)+1))

Code goes in next post since today I discovered that there's post length limit of 10K, and this would have 15K (thanks @r1c1 and all XenForo family).

(*) After all I found an inconsistency in your specs about the design. You said that:
Each colour represents a different parking time restriction. I.e Red = 2 hour limit Black may equal = 4 hours.
but your timing pattern doesn't work for different areas allowed times since you're collecting data 5 times each 2 hours and the pattern definition (5 zeros/ones) will only match with 2 hours areas.

What's missing is how you're gonna make the input of the ... 80! worksheets. If manually which I doubt (if so I'd fire your boss), if from a handheld device, if from a database, if...

Just advise if any issue.

Regards!
 

Attachments

  • Duration of Stay V2 - Duration of Stay & Occupancy 1st July (for NicGreen at chandoo.org).xlsm
    198.3 KB · Views: 7
Code part I of (who knows?, do I have to have a calculator at a hand?)

This is the main code, at a standard module:
Code:
Option Explicit

' global constants
'  worksheet & ranges
Global Const gksNoDataWS = "0"
Global Const gksArea = "AreaTable"
Global Const gksColor = "AreaColorList"
Global Const gksTime = "AreaTimeList"
Global Const gksRow = "AreaRowList"
Global Const gksTiming = "TimingList"
Global Const gksParkingI = "ParkingInputTable"
Global Const gksVehicle = "VehicleList"
Global Const gksParkingO = "ParkingOutputTable"

' public declarations
'  ranges
Dim grngA As Range, grngAC As Range, grngAT As Range, grngAR As Range, grngT As Range
Dim grngPI As Range, grngV As Range, grngPO As Range

Sub GonnaGetParkedAllTheTimeIWant_GotIt(Optional pvWS As Variant)
    '
    ' constants
    '  other
    Const kiAreaColor = 1
    Const kiAreaTime = 2
    Const kiColorIndex = 24
    Const ksPattern = "Parking Pattern"
    Const ksApostrophe = "'"
    Const ksDollar = "$"
    '
    ' declarations
    Dim rng1 As Range, rng2 As Range
    '  arrays
    Dim sColor() As String, iTime() As Integer, iRow() As Integer, dTiming() As Date
    Dim sVehicle() As String, sParkTime()
    '  others
    Dim sWS As String, iColor As Integer, iTiming As Integer
    Dim I As Long, J As Long, K As Long, L As Long, M As Long, N As Long, O As Long
    Dim A As String
    '
    ' start
    If IsMissing(pvWS) Then sWS = "" Else sWS = CStr(pvWS)
    '
    ' process
    For I = 1 To Worksheets.Count
        With Worksheets(I)
            If .Name <> gksNoDataWS Then
                If sWS = "" Or .Name = sWS Then
                    '
                    ' initialize
                    '  ranges
                    Set grngA = .Range(gksArea)
                    Set grngAC = .Range(gksColor)
                    Set grngAT = .Range(gksTime)
                    Set grngAR = .Range(gksRow)
                    Set grngT = .Range(gksTiming)
                    Set grngPI = .Range(gksParkingI)
                    Set grngV = .Range(gksVehicle)
                    Set grngPO = .Range(gksParkingO)
                    If grngV.Rows.Count > 1 Then
                        With grngV
                            Range(.Rows(2), .Rows(.Rows.Count)).ClearContents
                        End With
                        With grngPO
                            Range(.Rows(2), .Rows(.Rows.Count)).ClearContents
                        End With
                    End If
                    '  arrays
                    With grngA
                        iColor = .Rows.Count
                        ReDim sColor(iColor), iTime(iColor)
                        For K = 1 To iColor
                            sColor(K) = .Cells(K, 1).Value
                            iTime(K) = .Cells(K, 2).Value
                        Next K
                    End With
                    With grngT
                        iTiming = .Columns.Count
                        ReDim dTiming(iTiming)
                        For K = 1 To iTiming
                            dTiming(K) = .Cells(1, K).Value
                        Next K
                    End With
                    ' titles
                    Set rng1 = grngPO.Cells(1, 1)
                    Application.Union(grngV, grngPO).EntireColumn.Borders.LineStyle = xlNone
                    Application.Union(grngV, grngPO).EntireColumn.HorizontalAlignment = xlLeft
                    Range(rng1.Offset(-3, 0), rng1.Offset(-2, grngPO.Columns.Count)).Interior.ColorIndex = xlNone
                    Range(rng1.Offset(-3, 0), rng1.Offset(-0, grngPO.Columns.Count)).ClearContents
                    For K = 1 To iColor
                        L = (K - 1) * (iTiming + 1)
                        M = L + iTiming
                        Set rng2 = grngAC.Cells(K, 1)
                        Range(rng1.Offset(-3, L), rng1.Offset(-3, M)).Value = sColor(K)
                        Range(rng1.Offset(-3, L), rng1.Offset(-3, M)).Interior.Color = rng2.Interior.Color
                        Range(rng1.Offset(-2, L + 1), rng1.Offset(-2, M)).Interior.ColorIndex = kiColorIndex
                        rng1.Offset(0, L).Value = ksPattern
                        N = 0
                        For O = 1 To iTiming
                            rng1.Offset(-2, L + O).Value = N & "-" & N + iTime(K) & " hrs"
                            N = N + iTime(K)
                            rng1.Offset(0, L + O).Value = N
                        Next O
                    Next K
                    '
                    ' do the job
                    J = 0
                    ReDim sVehicle(J)
                    ReDim sParkTime(iColor, J)
                    '  read input
                    For K = 2 To grngPI.Rows.Count
                        ' area
                        A = grngPI.Cells(K, 1).Value
                        For L = 1 To iColor
                            If A = sColor(L) Then Exit For
                        Next L
                        If L > iColor Then
                            MsgBox "Unknown area for all vehicles at row " & _
                                grngPI.Cells(K, 1).Address(False, False).Row & _
                                " of worgksheet " & .Name, _
                                vbApplicationModal + vbCritical + vbOKOnly, "Area error"
                        End If
                        If L <= iColor Then
                            ' data
                            For M = 2 To grngPI.Columns.Count
                                ' vehicle
                                A = grngPI.Cells(K, M).Value
                                If A <> "" Then
                                    ' new?
                                    For N = 1 To J
                                        If A = sVehicle(N) Then Exit For
                                    Next N
                                    If N > J Then
                                        J = J + 1
                                        ReDim Preserve sVehicle(J)
                                        ReDim Preserve sParkTime(iColor, J)
                                        sVehicle(J) = A
                                        For O = 1 To iColor
                                            sParkTime(O, J) = String(iTiming, "0")
                                        Next O
                                    End If
                                    ' time
                                    If Mid(sParkTime(L, N), M - 1, 1) <> "0" Then
                                        MsgBox "Duplicate entry for vehicle " & sVehicle(N) & _
                                            " at timing " & Format(dTiming(M - 1), "hh:mm AM/PM") & _
                                            " (cell " & grngPI.Cells(K, M).Address(False, False) & ")" & _
                                            " of worgksheet " & .Name, _
                                            vbApplicationModal + vbCritical + vbOKOnly, "Duplicate data"
                                    Else
                                        Mid(sParkTime(L, N), M - 1, 1) = "1"
                                    End If
                                End If
                            Next M
                        End If
                    Next K
                    '
                    ' unique vehicles
                    For K = 1 To J
                        grngV.Cells(K + 1, 1).Value = sVehicle(K)
                        For L = 1 To iColor
                            M = (L - 1) * (iTiming + 1) + 1
                            grngPO.Cells(K + 1, M).Value = ksApostrophe & sParkTime(L, K)
                            For N = 1 To iTiming
                                grngPO.Cells(K + 1, M + N).Value = Val(Mid(sParkTime(L, K), N, 1))
                            Next N
                        Next L
                    Next K
                    ' formulas
                    '  vehicles
                    M = grngV.Row + 1
                    N = J + grngV.Row
                    A = grngV.Offset(-1, 0).Address(, False)
                    A = Left(A, InStr(A, ksDollar) - 1)
                    grngV.Cells(0, 1).Formula = "=COUNTA(" & A & M & ":" & A & N & ")"
                    '  parking output
                    M = grngPO.Row + 1
                    N = J + grngV.Row
                    For K = 1 To iColor
                        L = (K - 1) * (iTiming + 1)
                        For O = 1 To iTiming
                            A = rng1.Offset(-1, L + O).Address(, False)
                            A = Left(A, InStr(A, ksDollar) - 1)
                            rng1.Offset(-1, L + O).Formula = "=SUM(" & A & M & ":" & A & N & ")"
                        Next O
                    Next K
                    ' format
                    Application.Union(grngV, grngPO).EntireColumn.AutoFit
                    Application.Union(grngV, grngPO).Borders.LineStyle = xlContinuous
                    Application.Union(grngV, grngPO).EntireColumn.HorizontalAlignment = xlCenter
                    '
                    ' terminate
                    Set grngPO = Nothing
                    Set grngV = Nothing
                    Set grngPI = Nothing
                    Set grngT = Nothing
                    Set grngAR = Nothing
                    Set grngAT = Nothing
                    Set grngAC = Nothing
                    Set grngA = Nothing
                End If
            End If
        End With
    Next I
    '
    ' end
    Beep
    '
End Sub
 
Code part II of 2

Code:
Sub BombTheWholeParkingArea_ByeByeCars(Optional pvWS As Variant)
    ' constants
    ' declarations
    Dim sWS As String
    ' start
    If IsMissing(pvWS) Then sWS = "" Else sWS = CStr(pvWS)
    ' process
    SomeoneHasToDoTheDirtyJob sWS, False
    ' end
    Beep
End Sub
Sub PutTheOpenSignboardAtTheEntrance(Optional pvWS As Variant)
    ' constants
    ' declarations
    Dim sWS As String
    ' start
    If IsMissing(pvWS) Then sWS = "" Else sWS = CStr(pvWS)
    ' process
    SomeoneHasToDoTheDirtyJob sWS, True
    ' end
    Beep
End Sub
Private Sub SomeoneHasToDoTheDirtyJob(psWS As String, pbReset As Boolean)
    ' constants
    ' declarations
    Dim rng As Range
    Dim I As Long, J As Long, K As Long
    ' start
    ' process
    For I = 1 To Worksheets.Count
        If Worksheets(I).Name <> gksNoDataWS Then
            If psWS = "" Or Worksheets(I).Name = psWS Then
                ' ranges
                If pbReset Then
                    Set grngAC = Worksheets(I).Range(gksColor)
                    Set grngAR = Worksheets(I).Range(gksRow)
                End If
                Set grngPI = Worksheets(I).Range(gksParkingI)
                ' clear
                With grngPI
                    If .Rows.Count > 1 Then
                        With Range(.Rows(2), .Rows(.Rows.Count))
                            .ClearContents
                            .Borders.LineStyle = xlNone
                            .Interior.ColorIndex = xlNone
                        End With
                    End If
                End With
                ' build
                If pbReset Then
                    J = 1
                    For K = 1 To grngAC.Rows.Count
                        Set rng = Range(grngPI.Cells(J + 1, 1), _
                            grngPI.Cells(J + grngAR.Cells(K, 1).Value, 1))
                        grngAC.Cells(K, 1).Copy rng
                        Set rng = Range(grngPI.Cells(J + 1, 2), _
                            grngPI.Cells(J + grngAR.Cells(K, 1).Value, grngPI.Columns.Count))
                        grngAR.Cells(K, 1).Copy
                        rng.PasteSpecial xlPasteFormats
                        J = J + grngAR.Cells(K, 1).Value
                        Set grngPI = grngPI.Resize(J)
                    Next K
                End If
            End If
        End If
    Next I
    ' end
    Set grngPI = Nothing
    If pbReset Then
        Set grngAR = Nothing
        Set grngAC = Nothing
    End If
End Sub
 
Code part III of 3

And these are the codes for the worksheet's class modules (summary and 1 of 80):
Code:
Option Explicit
Private Sub CommandButton1_Click()
  GonnaGetParkedAllTheTimeIWant_GotIt
End Sub
Private Sub CommandButton2_Click()
  BombTheWholeParkingArea_ByeByeCars
  PutTheOpenSignboardAtTheEntrance
End Sub
Private Sub CommandButton3_Click()
  BombTheWholeParkingArea_ByeByeCars
End Sub
Code:
Option Explicit
Private Sub CommandButton1_Click()
  GonnaGetParkedAllTheTimeIWant_GotIt Me.Name
End Sub
Private Sub CommandButton2_Click()
  BombTheWholeParkingArea_ByeByeCars Me.Name
  PutTheOpenSignboardAtTheEntrance Me.Name
End Sub
Private Sub CommandButton3_Click()
  BombTheWholeParkingArea_ByeByeCars Me.Name
End Sub
 
That is amazing. Cannot thank you enough.

There is one error I have noticed though and it seems to be in the calculation of the stay duration.

Take for example the first vehicle NJLZ in the sheet. That vehicle has a parking pattern of 01100. Which means it was recorded twice at the 11am and 1pm recordings.

What the columns M-Q should read is 00100 indicating that the vehicle stayed for 4 hours however the columns read 01100 which means it stays for a period of 2 hours and then a period of 4 hours which is incorrect.

Here is a breakdown sample breakdown further illustrating various combo's

Code:
#                          &#60; 2 hrs  2-4 hrs 4-6 hrs 6-8 hrs 8-10 hrs
32  14  3  4  6
Unique  Parking Pattern        2    4  6  8  10
SAJAN  10011                  1    1  0  0  0
C383    11111                  0    0  0  0  1
M081    11000                  0    1  0  0  0
X705    11111                  0    0  0  0  1
B785    11111                  0    0  0  0  1
LIR1    10000                  1    0  0  0  0
K480    11000                  0    1  0  0  0
C732    11011                  0    2  0  0  0
O624    11111                  0    0  0  0  1
M222    11111                  0    0  0  0  1
H669    11010                  1    1  0  0  0
U945    10000                  1    0  0  0  0
K108    10010                  2    0  0  0  0

On reviewing my originally uploaded file it seems it had the same error. Which is odd considering it didn't have that previously.

Are you able to rectify this? Thanks for your work so far
 
Last edited:
Hi, NicGreen!

I understood that each position (i) of the parking pattern was a zero if it wasn't parked in the related area at the i-th time of registering data (9AM, 11AM, 1PM, 3PM, 5PM). Now considering the lilac 2nd row labels it's reasonable to change in the way you recently said. But to work only once, that would solve the issue of the different time allowed in different areas?

Regards!
 
Hi SirJB7,

In regards to to the different time intervals not matching up to the recording intervals, some assumptions are made post this investigation in regards to this which rectify any mismatch. Recording every two hours was a concession made due to resources available.

Hope this helps.
 
Hi, NicGreen!

Check the updated uploaded file. This are the changes in the code (above part 1):

Added at end of constants definition:
Code:
    Const ks0 = "0"
    Const ks1 = "1"
and changed a couple of times when before used "0" and "1".

Old:
Code:
                            For N = 1 To iTiming
                                grngPO.Cells(K + 1, M + N).Value = Val(Mid(sParkTime(L, K), N, 1))
                            Next N
New:
Code:
                            For N = 1 To iTiming
                                grngPO.Cells(K + 1, M + N).Value = 0
                            Next N
                            A = sParkTime(L, K) & ks0
                            N = 1
                            Do Until N = iTiming + 1
                                O = 0
                                Do Until N = iTiming + 1 Or Mid(A, N, 1) = ks0 And O <> 0
                                    If Mid(A, N, 1) = ks1 Then O = O + 1
                                    N = N + 1
                                    DoEvents
                                Loop
                                If O <> 0 Then grngPO.Cells(K + 1, M + O).Value = grngPO.Cells(K + 1, M + O).Value + 1
                            Loop

But it's still inconsistent with the different times allowed at different areas.

Just advise if any issue.

Regards!
 

Attachments

  • Duration of Stay V2 - Duration of Stay & Occupancy 1st July (for NicGreen at chandoo.org).xlsm
    199.2 KB · Views: 6
Thanks SirJB7 this works great, i've started to set the system up with all the worksheets and have found no issues. We still have that inconsistency but thats not going to be able to be removed without considerably increasing the surveillance time for car parks. However i have noticed that the Go All button may need to have a progress bar attached to it like http://www.experts-exchange.com/Sof...s-Bar-for-Excel-and-Other-Microsoft-Apps.html.

I'm currently working out a way to incorporate this into it.
 
I've managed to implement the button but need to still finalise how to make it count. I fugured it would need to be placed inside one of the loops but need to make it incrementally increase some how.

My thoughts would be to maybe do something along the lines of percentage complete = current row being processed / total number of rows? coding this however i am unsure.
 
Hi, NicGreen!

Status bar are for long processes and in the case of the sample file it took less than 6 seconds to run it 10 times, so running if for 80 parking areas it'd take 45 sec approximately: IMHO this doesn't require a progress bar at all. How much time it takes in your case?

Do this to check it:

In module Módulo1, procedure GonnaGetParkedAllTheTimeIWant_GotIt:
a) Add this sentence after the last Dim clause
Code:
    Dim II As Long
b) Add this:
Code:
    For II = 1 To 10
before this:
Code:
    For I = 1 To Worksheets.Count
c) Add this:
Code:
    Next II
after this:
Code:
    Next I
c) Add this:

In class module Hoja0, procedure CommandButton1_Click:
a) Insert this:
Code:
    Debug.Print Now()
after and before the only line that it has.

Press GoAll button to test it 10 times. If they differ considerably with my posted figures, please post your hardware configuration and upload a sample file with actual data (in quantity, not necessarily in quality).

Regards!
 
Hi, NicGreen!
I was beginning to get worried, since it should ran fast as it works in memory filling arrays and only at the end dumps the results.
Glad you solved it. Thanks for your feedback and for your kind words too. And welcome back whenever needed or wanted.
Regards!
 
Hi SirJB7.

Just a thought, in terms of addressing the inconsistency in the formula in regards to say 1 hr parking taken every 2 hours. Is it possible to add a column next to the 'max' column (which specifies the interval) which would specify the number of recording periods e.g

If it were taken every two hours recordings would occur at 9am/11am/1pm/3pm/5pm hence a total of 5 periods while if it were 1hr it would be 9am/10am/11am/12pm/1pm/2pm/3pm/4pm/5pm totally 9 periods.

That way the inconsistency would be removed and if i wanted to record every 1hr for a park i would simply change the max to 1 and the recording periods to 9.

Sorry for all the persistent questions you have been a great help.
 
Hi, NicGreen!

But then you'll have a variable TimingList of 5 and 9 columns, but that's per area! So read area will have 5 measures, black 9, blue 9, ... too messy for the input, not for the model. The logic process is to register parking at each hour and then -having all areas 9 columns- make the output be of 5 or 9 columns according to the new parameter next to Max column.

This would be V2... and I guess that it was free up to V2.

Regards!
 
Completely understand. If needed i most certainly will come to you for future paid requests to return the generosity you have shown myself. For the interim i may be able to get around it using the old formula based approach.

Regards,
 
Hi, NicGreen!

Actually it's not a matter of money since we all here contribute only to help other people, but it'd be a nice exercise for you to expand the V2 features to the reach the V3 functionality; otherwise you'd never end managing that workbook...

Despite of this there are lot of things that some could and some should be done to the V2 workbook to turn it into a usable tool:
- put area maps (A3:E11) in an auxiliary worksheet
- build an area table with that map and the info in H3:H7 and F9:I11
- make worksheet 0 a bit more intelligent, with access to the areas by name, map

And most important of all: data collection
- how is data registered and entered
- who does this
- what about history?

However this are my personal thoughts about how to enhance this model, but it'll all depend on the real scope of this project, and talking about scopes perhaps this V3 exceeds by far the original one of your initial requirement.

Regards!
 
Last edited:
Back
Top