Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Stojcheska Teodora
Programming_Project
Commits
d010c95a
Commit
d010c95a
authored
Jul 25, 2021
by
Stojcheska Teodora
Browse files
Merged reorderCalendar to work for both add and delete task, fixed exeption bug for fixed tasks
parent
b930c504
Changes
4
Hide whitespace changes
Inline
Side-by-side
Calendar.cs
View file @
d010c95a
...
...
@@ -58,14 +58,15 @@ public class Calendar
return
hours
;
}
// TODO: change funtion let it just accept parameter date
public
void
addDaysUpToDate
(
DateTime
date
,
int
duration
)
{
int
daysToAdd
;
daysToAdd
=
numberOfDaysInRange
(
Days
[
Days
.
Count
-
1
].
Date
,
date
)
-
1
;
daysToAdd
=
(
int
)
Math
.
Ceiling
((
double
)
duration
/
DefaultWorkingHours
)
;
for
(
int
i
=
0
;
i
<
daysToAdd
;
++
i
)
{
if
(
duration
==
0
||
!
isDateValid
(
Days
[
Days
.
Count
-
1
].
Date
.
AddDays
(
1
),
date
)
)
if
(
duration
==
0
)
{
break
;
}
...
...
@@ -76,11 +77,6 @@ public class Calendar
Days
.
Add
(
newDay
);
duration
=
duration
>=
newDay
.
WorkingHours
||
duration
<
0
?
(
duration
-
newDay
.
WorkingHours
)
:
0
;
}
if
(
duration
>
0
)
{
throw
new
NoSpaceForTaskExeption
(
"No space to add task"
);
}
}
public
List
<
Day
>
getRangeOfDaysForTask
(
Task
task
)
...
...
@@ -90,7 +86,6 @@ public class Calendar
int
shouldAddDayHours
=
shouldAddDay
(
task
);
if
(
shouldAddDayHours
>
0
)
{
Day
day
=
isDateValid
(
Days
[
Days
.
Count
-
1
].
Date
,
DateTime
.
Now
)
?
Days
[
Days
.
Count
-
1
]
:
Days
[
0
];
addDaysUpToDate
(
task
.
Deadline
,
shouldAddDayHours
);
}
...
...
@@ -131,34 +126,41 @@ public class Calendar
{
if
(
exception
.
Day
!=
null
)
{
Day
day
=
getDayByDate
(
task
.
Deadline
);
// ???????????????
// getDayByDate(task.Deadline)
Day
day
=
exception
.
Day
;
day
.
removeTask
(
task
);
deleteReorderCalendar
(
exception
.
Day
.
NextDay
,
day
.
hoursToShift
*
-
1
,
day
);
if
(
day
.
hoursToShift
>
0
)
{
reorderCalendar
(
day
,
day
.
hoursToShift
,
null
,
Direction
.
NEXT
);
}
reorderCalendar
(
exception
.
Day
.
NextDay
,
day
.
hoursToShift
*
-
1
,
day
,
Direction
.
PREVIOUS
);
}
ErrorInTaskParameters
?.
Invoke
();
}
}
// have tasks add fixed ex 27 and add long
// now fixed is entangled between the long
// also try to have a task whose deadline is after the long tasks deadline and try deleting the long task
public
void
_addFixedTask
(
Task
task
)
{
Day
day
;
if
(
numberOfDaysInRange
(
task
.
Deadline
,
Days
[
Days
.
Count
-
1
].
Date
)
>
0
){
day
=
getDayByDate
(
task
.
Deadline
);
day
.
addTask
(
task
,
0
);
reorderCalendar
(
day
,
task
.
Duration
);
int
shouldAddDayHours
=
shouldAddDay
(
task
);
if
(
shouldAddDayHours
>
0
)
{
addDaysUpToDate
(
task
.
Deadline
,
shouldAddDayHours
);
}
else
if
(
numberOfDaysInRange
(
task
.
Deadline
,
Days
[
Days
.
Count
-
1
].
Date
)
<=
0
)
{
while
(
numberOfDaysInRange
(
task
.
Deadline
,
Days
[
Days
.
Count
-
1
].
Date
)
<=
0
)
{
Day
newDay
=
new
Day
(
Days
[
Days
.
Count
-
1
].
Date
.
AddDays
(
1
),
new
List
<
Task
>(),
DefaultWorkingHoursInterval
,
DefaultWorkingHours
);
Days
[
Days
.
Count
-
1
].
NextDay
=
newDay
;
newDay
.
PrevDay
=
Days
[
Days
.
Count
-
1
];
Days
.
Add
(
newDay
);
}
day
=
getDayByDate
(
task
.
Deadline
);
day
.
addTask
(
task
,
0
);
addDaysUpToDate
(
task
.
Deadline
,
numberOfDaysInRange
(
Days
[
Days
.
Count
-
1
].
Date
,
task
.
Deadline
));
}
Day
day
=
getDayByDate
(
task
.
Deadline
);
day
.
addTask
(
task
,
0
);
if
(
day
.
isDayFull
(
0
))
{
reorderCalendar
(
day
,
day
.
hoursToShift
,
null
,
Direction
.
NEXT
);
}
}
...
...
@@ -176,7 +178,7 @@ public class Calendar
day
.
addTask
(
task
,
i
);
if
(
day
.
isDayFull
(
0
))
{
reorderCalendar
(
day
,
day
.
hoursToShift
);
reorderCalendar
(
day
,
day
.
hoursToShift
,
null
,
Direction
.
NEXT
);
}
return
;
}
...
...
@@ -186,22 +188,24 @@ public class Calendar
day
.
addTask
(
task
,
day
.
Tasks
.
Count
);
if
(
day
.
isDayFull
(
0
))
{
reorderCalendar
(
day
,
day
.
hoursToShift
);
reorderCalendar
(
day
,
day
.
hoursToShift
,
null
,
Direction
.
NEXT
);
}
return
;
}
}
}
private
void
reorderCalendar
(
Day
day
,
int
hours
)
public
bool
checkForCondition
(
int
i
,
int
end
,
Direction
dir
)
=>
dir
==
Direction
.
NEXT
?
i
>=
end
:
i
<
end
;
public
void
reorderCalendar
(
Day
day
,
int
hours
,
Day
returnPoint
,
Direction
dir
)
{
Day
dirDay
=
d
ay
.
Next
Day
;
Day
dirDay
=
d
ir
==
Direction
.
NEXT
?
day
.
NextDay
:
day
.
Prev
Day
;
if
(
dirDay
==
null
||
day
.
hoursToShift
<=
0
)
{
return
;
}
if
(
dirDay
==
null
||
(
dirDay
.
Equals
(
returnPoint
)
&&
dir
==
Direction
.
PREVIOUS
)
||
(
day
.
hoursToShift
<=
0
&&
dir
==
Direction
.
NEXT
)
)
{
return
;
}
List
<
Task
>
tasks
=
new
List
<
Task
>();
for
(
int
i
=
d
ay
.
Tasks
.
Count
-
1
;
i
>=
0
;
--
i
)
for
(
int
i
=
d
ir
==
Direction
.
NEXT
?
day
.
Tasks
.
Count
-
1
:
0
;
checkForCondition
(
i
,
(
dir
==
Direction
.
NEXT
?
0
:
day
.
Tasks
.
Count
),
dir
);
i
+=
(
int
)
dir
)
{
if
(
day
.
Tasks
[
i
].
Type
!=
Type
.
FIXED
)
{
...
...
@@ -211,33 +215,43 @@ public class Calendar
if
(!
isDateValid
(
dirDay
.
Date
,
curTask
.
Deadline
))
{
foreach
(
Task
task
in
tasks
)
{
day
.
addTask
(
task
,
day
.
Tasks
.
Count
);
}
throw
new
NoSpaceForTaskExeption
(
"There is no space to add the Task, error occured during shifting the Tasks"
,
day
,
curTask
,
hours
);
}
Task
curTaskDir
=
curTask
.
getTaskByDirection
(
dir
);
if
(
curTask
.
Duration
>
hours
)
{
int
additionalHours
=
0
;
if
(
curTask
.
IsSplit
)
if
(
curTask
Dir
!=
null
)
{
additionalHours
=
curTask
.
SplitTaskPt
r
.
Duration
;
dirDay
.
removeTask
(
curTask
.
SplitTaskPt
r
);
curTask
.
mergeTasks
(
curTask
,
curTask
.
SplitTaskPt
r
);
additionalHours
=
curTask
Di
r
.
Duration
;
dirDay
.
removeTask
(
curTask
Di
r
);
curTask
.
mergeTasks
(
curTask
,
curTask
Di
r
);
}
int
[]
splitHours
=
{
curTask
.
Duration
-
hours
-
additionalHours
,
hours
+
additionalHours
};
curTask
.
splitTask
(
splitHours
,
0
,
curTask
,
day
);
curTask
.
splitTask
(
splitHours
,
0
,
curTask
,
day
,
dir
);
hours
=
0
;
tasks
.
Add
(
curTask
.
Spli
tTask
Ptr
);
tasks
.
Add
(
curTask
.
ge
tTask
ByDirection
(
dir
)
);
}
else
{
int
curTaskHours
=
curTask
.
Duration
;
if
(
curTask
.
IsSplit
)
if
(
curTask
Dir
!=
null
)
{
dirDay
.
removeTask
(
curTask
.
SplitTaskPtr
);
curTask
.
mergeTasks
(
curTask
,
curTask
.
SplitTaskPtr
);
dirDay
.
removeTask
(
curTaskDir
);
if
(
dir
==
Direction
.
NEXT
)
{
curTask
.
mergeTasks
(
curTask
,
curTaskDir
);
tasks
.
Add
(
curTask
);
}
else
{
curTaskDir
.
mergeTasks
(
curTaskDir
,
curTask
);
tasks
.
Add
(
curTaskDir
);
}
}
else
{
...
...
@@ -245,103 +259,36 @@ public class Calendar
}
hours
-=
curTaskHours
;
day
.
removeTask
(
curTask
);
dirDay
.
addTask
(
curTask
,
0
);
}
}
}
foreach
(
Task
task
in
tasks
)
{
dirDay
.
addTask
(
task
,
0
);
}
reorderCalendar
(
dirDay
,
dirDay
.
hoursToShift
);
}
/* ------------------------------- Delete Task ----------------------------------- */
private
void
deleteReorderCalendar
(
Day
day
,
int
hours
,
Day
returnPoint
)
{
int
h
=
hours
;
Day
dirDay
=
day
.
PrevDay
;
if
(
dirDay
==
null
||
day
.
Equals
(
returnPoint
))
{
return
;
}
List
<
Task
>
tasks
=
new
List
<
Task
>();
for
(
int
i
=
0
;
i
<
day
.
Tasks
.
Count
;
++
i
)
{
if
(
day
.
Tasks
[
i
].
Type
!=
Type
.
FIXED
)
{
if
(
hours
==
0
)
{
break
;
}
Task
curTask
=
day
.
Tasks
[
i
];
if
(
curTask
.
Duration
>
hours
)
{
Task
shiftSplitTask
=
new
Task
(
curTask
.
Name
,
curTask
.
Deadline
,
hours
,
curTask
.
Type
,
true
);
shiftSplitTask
.
SplitTaskPtr
=
curTask
;
curTask
.
Duration
-=
hours
;
tasks
.
Add
(
shiftSplitTask
);
hours
=
0
;
}
else
{
int
curTaskHours
=
curTask
.
Duration
;
tasks
.
Add
(
curTask
);
hours
-=
curTaskHours
;
day
.
removeTask
(
curTask
);
i
--;
if
(
dir
==
Direction
.
PREVIOUS
)
{
i
--;
}
}
}
}
if
(
dirDay
.
Tasks
.
Count
!=
0
&&
dirDay
.
Tasks
[
dirDay
.
Tasks
.
Count
-
1
].
IsSplit
&&
tasks
.
Count
>
0
)
{
dirDay
.
Tasks
[
dirDay
.
Tasks
.
Count
-
1
].
IsSplit
=
tasks
[
0
].
IsSplit
;
dirDay
.
Tasks
[
dirDay
.
Tasks
.
Count
-
1
].
SplitTaskPtr
=
tasks
[
0
].
SplitTaskPtr
;
dirDay
.
Tasks
[
dirDay
.
Tasks
.
Count
-
1
].
Duration
+=
tasks
[
0
].
Duration
;
tasks
.
RemoveAt
(
0
);
}
for
(
int
i
=
0
;
i
<
tasks
.
Count
;
++
i
)
{
dirDay
.
addTask
(
tasks
[
i
],
dirDay
.
Tasks
.
Count
);
}
foreach
(
Task
task
in
tasks
)
{
dirDay
.
addTask
(
task
,
dir
==
Direction
.
NEXT
?
0
:
dirDay
.
Tasks
.
Count
);
}
deleteR
eorderCalendar
(
dirDay
,
h
,
returnPoint
);
r
eorderCalendar
(
dirDay
,
dirDay
.
hoursToShift
,
returnPoint
,
dir
);
}
public
void
deleteTaskHelper
(
Day
day
,
Task
task
)
/* ------------------------------- Delete Task ----------------------------------- */
public
void
deleteTask
(
Day
day
,
Task
task
)
{
int
hours
=
0
;
if
(
task
.
IsSplit
)
while
(
task
.
NextSplitTaskPtr
!=
null
)
{
hours
+=
task
.
SplitTaskPtr
.
Duration
;
day
.
NextDay
.
removeTask
(
task
.
SplitTaskPtr
);
task
.
IsSplit
=
false
;
deleteReorderCalendar
(
Days
[
Days
.
Count
-
1
],
task
.
SplitTaskPtr
.
Duration
,
day
.
NextDay
);
task
=
task
.
NextSplitTaskPtr
;
day
=
day
.
NextDay
;
}
while
(
day
.
PrevDay
!=
null
&&
day
.
PrevDay
.
Tasks
.
Count
!=
0
&&
(
day
.
PrevDay
.
Tasks
[
day
.
PrevDay
.
Tasks
.
Count
-
1
].
IsSplit
&&
day
.
PrevDay
.
Tasks
[
day
.
PrevDay
.
Tasks
.
Count
-
1
].
Name
==
task
.
Name
)
)
while
(
task
!=
null
)
{
hours
+=
day
.
PrevDay
.
Tasks
[
day
.
PrevDay
.
Tasks
.
Count
-
1
].
Duration
;
deleteTaskHelper
(
day
.
PrevDay
,
day
.
PrevDay
.
Tasks
[
day
.
PrevDay
.
Tasks
.
Count
-
1
]);
}
day
.
removeTask
(
task
);
task
.
NextSplitTaskPtr
=
null
;
hours
+=
task
.
Duration
;
day
.
removeTask
(
task
);
deleteReorderCalendar
(
Days
[
Days
.
Count
-
1
],
task
.
Duration
,
day
);
task
.
Duration
=
hours
;
}
reorderCalendar
(
Days
[
Days
.
Count
-
1
],
task
.
Duration
,
day
.
PrevDay
,
Direction
.
PREVIOUS
);
public
void
deleteTask
(
Day
day
,
Task
task
)
{
while
(
task
.
IsSplit
)
{
task
=
task
.
SplitTaskPtr
;
day
=
day
.
NextDay
;
task
=
task
.
PrevSplitTaskPtr
;
day
=
day
.
PrevDay
;
}
deleteTaskHelper
(
day
,
task
);
}
/* --------------------------- Change Working Hours ------------------------------- */
...
...
@@ -351,11 +298,52 @@ public class Calendar
Day
day
=
getDayByDate
(
date
);
if
(
previousWorkingHours
-
day
.
WorkingHours
<
0
)
{
deleteR
eorderCalendar
(
Days
[
Days
.
Count
-
1
],
Math
.
Abs
(
previousWorkingHours
-
day
.
WorkingHours
),
day
);
r
eorderCalendar
(
Days
[
Days
.
Count
-
1
],
Math
.
Abs
(
previousWorkingHours
-
day
.
WorkingHours
),
day
,
Direction
.
PREVIOUS
);
}
else
if
(
previousWorkingHours
-
day
.
WorkingHours
>
0
)
{
reorderCalendar
(
day
,
previousWorkingHours
-
day
.
WorkingHours
);
// call add days upto date
// shrinking the working day, may need to add days
for
(
int
i
=
0
;
i
<
(
int
)
Math
.
Ceiling
((
double
)
previousWorkingHours
/
day
.
WorkingHours
);
++
i
)
{
Days
.
Add
(
new
Day
(
Days
[
Days
.
Count
].
Date
.
AddDays
(
1
),
new
List
<
Task
>(),
DefaultWorkingHoursInterval
,
DefaultWorkingHours
));
}
try
{
reorderCalendar
(
day
,
previousWorkingHours
-
day
.
WorkingHours
,
null
,
Direction
.
NEXT
);
}
catch
(
NoSpaceForTaskExeption
exception
)
{
day
.
WorkingHours
=
previousWorkingHours
;
if
(
exception
.
Day
!=
null
)
{
reorderCalendar
(
exception
.
Day
.
NextDay
,
day
.
hoursToShift
*
-
1
,
day
,
Direction
.
PREVIOUS
);
}
ErrorInTaskParameters
?.
Invoke
();
}
}
}
// check if default wokring hours is used somewhere
// also if the addition of days is handled in the above function
// adding days uses default working hours
// when i get to adding days its good to have the default working hours set right
// reorder assumes it has enough days
// i should add new days in changeWokringHours
public
void
changeDefaultWorkingHours
((
int
,
int
)
workingHoursInterval
)
{
this
.
DefaultWorkingHours
=
workingHoursInterval
.
Item2
-
workingHoursInterval
.
Item1
;
this
.
DefaultWorkingHoursInterval
=
workingHoursInterval
;
Day
day
=
getDayByDate
(
DateTime
.
Now
);
day
.
WorkingHours
=
this
.
DefaultWorkingHours
;
day
.
WorkingHoursInterval
=
this
.
DefaultWorkingHoursInterval
;
while
(
day
!=
null
)
{
changeWorkingHours
(
day
.
Date
,
day
.
WorkingHours
);
day
=
day
.
NextDay
;
}
}
}
\ No newline at end of file
Program.cs
View file @
d010c95a
...
...
@@ -3,7 +3,7 @@ using static System.Console;
using
System.Windows.Forms
;
static
class
Program
{
private
const
int
totalTests
=
9
;
private
const
int
totalTests
=
13
;
private
static
int
totalPassed
=
0
;
static
void
assert
(
bool
b
)
...
...
@@ -31,10 +31,13 @@ static class Program
t
=
new
Task
(
"a long task"
,
DateTime
.
Today
.
AddDays
(
30
),
100
,
Type
.
NORMAL
,
false
);
cal
.
addTask
(
t
);
assert
(
current
.
Tasks
.
Count
==
1
);
cal
.
deleteTask
(
current
,
t
);
assert
(
current
.
Tasks
.
Count
==
0
);
// Error - No space in the day
t
=
new
Task
(
"error"
,
DateTime
.
Now
,
20
,
Type
.
NORMAL
,
false
);
assert
(
current
.
Tasks
.
Count
==
0
);
// Error
t
=
new
Task
(
"buy groceries"
,
DateTime
.
Today
,
5
,
Type
.
NORMAL
,
false
);
...
...
@@ -42,6 +45,7 @@ static class Program
Task
t1
=
new
Task
(
"clean room"
,
DateTime
.
Today
.
AddDays
(
2
),
5
,
Type
.
NORMAL
,
false
);
cal
.
addTask
(
t1
);
// will throw error
/*******************Not throwing an exeption******************/
Task
t2
=
new
Task
(
"do homework"
,
DateTime
.
Today
,
5
,
Type
.
NORMAL
,
false
);
cal
.
addTask
(
t2
);
assert
(
current
.
Tasks
.
Count
==
2
);
...
...
@@ -75,21 +79,23 @@ static class Program
{
try
{
Settings
.
Load
();
test
();
if
(
Environment
.
OSVersion
.
Version
.
Major
>=
6
)
SetProcessDPIAware
();
Application
.
EnableVisualStyles
();
Application
.
SetCompatibleTextRenderingDefault
(
false
);
Application
.
Run
(
new
Scheduler
.
Forms
.
CalendarView
());
WriteLine
(
$"
{
totalPassed
}
/
{
totalTests
}
Passed!\n"
+
$"
{
totalTests
-
totalPassed
}
remain unexecuted!\n"
);
}
catch
(
Exception
e
)
catch
(
Exception
)
{
WriteLine
(
$"
{
totalPassed
}
/
{
totalTests
}
Passed!\n"
+
$"
{
totalTests
-
totalPassed
}
remain unexecuted!\n"
+
$"Failed at assert number:
{
totalPassed
+
1
}
"
);
}
Settings
.
Load
();
if
(
Environment
.
OSVersion
.
Version
.
Major
>=
6
)
SetProcessDPIAware
();
Application
.
EnableVisualStyles
();
Application
.
SetCompatibleTextRenderingDefault
(
false
);
Application
.
Run
(
new
Scheduler
.
Forms
.
CalendarView
());
}
[
System
.
Runtime
.
InteropServices
.
DllImport
(
"user32.dll"
)]
...
...
Scheduler.csproj
View file @
d010c95a
...
...
@@ -68,7 +68,6 @@
<Compile
Include=
"Program.cs"
/>
<Compile
Include=
"ProgramData.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Properties\Class1.cs"
/>
<Compile
Include=
"Settings.cs"
/>
<Compile
Include=
"Task.cs"
/>
<EmbeddedResource
Include=
"Controls\DatePicker.resx"
>
...
...
Task.cs
View file @
d010c95a
...
...
@@ -2,6 +2,7 @@
using
static
System
.
Console
;
public
enum
Type
{
FIXED
,
NORMAL
}
public
enum
Direction
{
PREVIOUS
=
1
,
NEXT
=
-
1
}
[
Serializable
]
public
class
Task
...
...
@@ -12,7 +13,8 @@ public class Task
public
int
Duration
{
get
;
set
;
}
public
Type
Type
{
get
;
set
;
}
public
bool
IsSplit
{
get
;
set
;
}
public
Task
SplitTaskPtr
{
get
;
set
;
}
public
Task
NextSplitTaskPtr
{
get
;
set
;
}
public
Task
PrevSplitTaskPtr
{
get
;
set
;
}
public
Task
(
string
name
,
DateTime
deadline
,
int
duration
,
Type
type
,
bool
isSplit
)
...
...
@@ -22,7 +24,7 @@ public class Task
this
.
Duration
=
duration
;
this
.
Type
=
type
;
this
.
IsSplit
=
isSplit
;
this
.
SplitTaskPtr
=
null
;
this
.
Next
SplitTaskPtr
=
null
;
}
public
override
bool
Equals
(
Object
obj
)
...
...
@@ -40,17 +42,36 @@ public class Task
public
override
int
GetHashCode
()
=>
Name
.
GetHashCode
();
public
void
splitTask
(
int
[]
hours
,
int
index
,
Task
task
,
Day
day
)
public
void
splitTask
(
int
[]
hours
,
int
index
,
Task
task
,
Day
day
,
Direction
dir
)
{
task
.
Duration
=
hours
[
0
];
task
.
IsSplit
=
true
;
task
.
SplitTaskPtr
=
new
Task
(
Name
,
Deadline
,
hours
[
1
],
Type
,
false
);
if
(
dir
==
Direction
.
NEXT
)
{
task
.
NextSplitTaskPtr
=
new
Task
(
Name
,
Deadline
,
hours
[
1
],
Type
,
false
);
task
.
NextSplitTaskPtr
.
PrevSplitTaskPtr
=
task
;
}
else
{
task
.
PrevSplitTaskPtr
=
new
Task
(
Name
,
Deadline
,
hours
[
1
],
Type
,
false
);
task
.
PrevSplitTaskPtr
.
NextSplitTaskPtr
=
task
;
}
}
public
void
mergeTasks
(
Task
firstTask
,
Task
secondTask
)
{
firstTask
.
Duration
+=
secondTask
.
Duration
;
firstTask
.
IsSplit
=
secondTask
.
IsSplit
;
firstTask
.
SplitTaskPtr
=
secondTask
.
SplitTaskPtr
;
firstTask
.
NextSplitTaskPtr
=
secondTask
.
NextSplitTaskPtr
;
}
public
Task
getTaskByDirection
(
Direction
dir
)
{
if
(
dir
==
Direction
.
PREVIOUS
)
{
return
this
.
PrevSplitTaskPtr
;
}
return
this
.
NextSplitTaskPtr
;
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment