Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Simonstrator
PeerfactSim.KOM
Commits
d6e05af0
Commit
d6e05af0
authored
Jan 24, 2019
by
Julian Zobel
Browse files
Put all other ITransition Strategies useing the abstract class
parent
74fef9c4
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/AbstractAttractionBasedTransitionStrategy.java
View file @
d6e05af0
...
...
@@ -29,6 +29,8 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Random
;
import
java.util.Set
;
import
de.tud.kom.p2psim.api.scenario.ConfigurationException
;
import
de.tud.kom.p2psim.api.topology.movement.SimLocationActuator
;
import
de.tudarmstadt.maki.simonstrator.api.Randoms
;
import
de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint
;
...
...
@@ -51,6 +53,12 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran
private
List
<
AttractionAssignmentListener
>
listeners
=
new
LinkedList
<>();
private
long
pauseTimeMin
=
0
;
private
long
pauseTimeMax
=
0
;
protected
final
static
int
EVENT_PAUSE_ENDED
=
1
;
@Override
public
AttractionPoint
getAssignment
(
SimLocationActuator
comp
)
{
return
assignments
.
get
(
comp
);
...
...
@@ -100,4 +108,24 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran
this
.
assignments
.
put
(
comp
,
attractionPoint
);
notifyListenersOfAssignmentUpdate
(
comp
,
attractionPoint
);
}
protected
long
getPauseTime
()
{
return
(
long
)
(
rnd
.
nextDouble
()
*
(
pauseTimeMax
-
pauseTimeMin
))
+
pauseTimeMin
;
}
public
void
setMinPauseTime
(
long
minPauseTime
)
{
if
(
minPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MinPauseTime should be >= 0!"
);
}
this
.
pauseTimeMin
=
minPauseTime
;
}
public
void
setMaxPauseTime
(
long
maxPauseTime
)
{
if
(
maxPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MaxPauseTime should be >= 0!"
);
}
this
.
pauseTimeMax
=
maxPauseTime
;
}
}
src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/FixedAssignmentStrategy.java
View file @
d6e05af0
...
...
@@ -20,20 +20,14 @@
package
de.tud.kom.p2psim.impl.topology.movement.modularosm.transition
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
de.tud.kom.p2psim.api.common.SimHost
;
import
de.tud.kom.p2psim.api.common.SimHostComponent
;
import
de.tud.kom.p2psim.api.topology.movement.SimLocationActuator
;
import
de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel
;
import
de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy.AttractionAssignmentListener
;
import
de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint
;
/**
...
...
@@ -43,14 +37,10 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
* @author Martin Hellwig
* @version 1.0, 07.07.2015
*/
public
class
FixedAssignmentStrategy
implements
I
TransitionStrategy
{
public
class
FixedAssignmentStrategy
extends
AbstractAttractionBased
TransitionStrategy
{
private
List
<
SimLocationActuator
>
comps
=
new
LinkedList
<
SimLocationActuator
>();
private
LinkedHashSet
<
AttractionPoint
>
aPoints
=
new
LinkedHashSet
<
AttractionPoint
>();
private
Map
<
SimLocationActuator
,
AttractionPoint
>
assignments
=
new
LinkedHashMap
<
SimLocationActuator
,
AttractionPoint
>();
private
Map
<
SimLocationActuator
,
SimHost
>
mappingMSHost
=
new
LinkedHashMap
<
SimLocationActuator
,
SimHost
>();
private
Map
<
SimHost
,
SimLocationActuator
>
mappingHostMS
=
new
LinkedHashMap
<
SimHost
,
SimLocationActuator
>();
...
...
@@ -58,36 +48,8 @@ public class FixedAssignmentStrategy implements ITransitionStrategy {
private
Map
<
String
,
AttractionPoint
>
mappingGroupIdAP
=
new
LinkedHashMap
<
String
,
AttractionPoint
>();
private
Map
<
AttractionPoint
,
String
>
mappingAPGroupId
=
new
LinkedHashMap
<
AttractionPoint
,
String
>();
private
List
<
AttractionAssignmentListener
>
listeners
=
new
LinkedList
<>();
@Override
public
AttractionPoint
getAssignment
(
SimLocationActuator
comp
)
{
return
assignments
.
get
(
comp
);
}
@Override
public
void
setAttractionPoints
(
Collection
<
AttractionPoint
>
attractionPoints
)
{
aPoints
.
addAll
(
attractionPoints
);
}
@Override
public
Set
<
AttractionPoint
>
getAllAttractionPoints
()
{
return
aPoints
;
}
@Override
public
void
addAttractionAssignmentListener
(
AttractionAssignmentListener
listener
)
{
listeners
.
add
(
listener
);
}
@Override
public
void
removeAttractionAssignmentListener
(
AttractionAssignmentListener
listener
)
{
listeners
.
remove
(
listener
);
}
@Override
public
void
addComponent
(
SimLocationActuator
ms
)
{
comps
.
add
(
ms
);
...
...
@@ -95,14 +57,14 @@ public class FixedAssignmentStrategy implements ITransitionStrategy {
// No assignments been done before.
if
(
assignments
.
isEmpty
())
{
AttractionPoint
aPoint
=
aPoints
.
iterator
().
next
();
AttractionPoint
aPoint
=
a
ttraction
Points
.
iterator
().
next
();
assignments
.
put
(
ms
,
aPoint
);
mappingGroupId
(
ms
,
aPoint
);
}
// GroupId is not mapped.
else
if
(!
mappingGroupIdAP
.
containsKey
(
mappingMSHost
.
get
(
ms
)
.
getProperties
().
getGroupID
()))
{
for
(
AttractionPoint
actAP
:
aPoints
)
{
for
(
AttractionPoint
actAP
:
a
ttraction
Points
)
{
if
(!
mappingAPGroupId
.
containsKey
(
actAP
))
{
assignments
.
put
(
ms
,
actAP
);
mappingGroupId
(
ms
,
actAP
);
...
...
@@ -120,7 +82,7 @@ public class FixedAssignmentStrategy implements ITransitionStrategy {
throw
new
Error
(
"Should not happen."
);
}
listeners
.
forEach
(
listener
->
listener
.
updatedAttraction
Assignment
(
ms
,
assignments
.
get
(
ms
))
)
;
notifyListenersOf
Assignment
Update
(
ms
,
assignments
.
get
(
ms
));
}
...
...
@@ -133,7 +95,7 @@ public class FixedAssignmentStrategy implements ITransitionStrategy {
public
void
updateTargetAttractionPoint
(
SimLocationActuator
comp
,
AttractionPoint
attractionPoint
)
{
assignments
.
put
(
comp
,
attractionPoint
);
listeners
.
forEach
(
listener
->
listener
.
updatedAttraction
Assignment
(
comp
,
attractionPoint
)
)
;
notifyListenersOf
Assignment
Update
(
comp
,
attractionPoint
);
}
private
void
mappingHost
(
SimLocationActuator
ms
)
{
...
...
src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/InAreaRoamingTransitionStrategy.java
View file @
d6e05af0
...
...
@@ -24,7 +24,6 @@ import java.util.LinkedHashMap;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
de.tud.kom.p2psim.api.scenario.ConfigurationException
;
import
de.tud.kom.p2psim.api.topology.movement.SimLocationActuator
;
import
de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel
;
import
de.tudarmstadt.maki.simonstrator.api.Event
;
...
...
@@ -43,15 +42,9 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
public
static
enum
roamingTransitionState
{
ROAMING
,
TRANSITION
}
private
final
static
int
EVENT_ROAMING_ENDED
=
1
;
}
protected
Map
<
SimLocationActuator
,
roamingTransitionState
>
roamingStates
=
new
LinkedHashMap
<>();
private
long
pauseTimeMin
=
0
;
private
long
pauseTimeMax
=
0
;
@Override
public
void
addComponent
(
SimLocationActuator
comp
)
{
...
...
@@ -66,7 +59,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
// start roaming
if
(
roamingStates
.
get
(
comp
)
==
roamingTransitionState
.
TRANSITION
)
{
// schedule the end of the roaming phase, which will make a new transition
Event
.
scheduleWithDelay
(
getPauseTime
(),
this
,
comp
,
EVENT_
ROAMING
_ENDED
);
Event
.
scheduleWithDelay
(
getPauseTime
(),
this
,
comp
,
EVENT_
PAUSE
_ENDED
);
this
.
roamingStates
.
put
(
comp
,
roamingTransitionState
.
ROAMING
);
}
...
...
@@ -93,31 +86,12 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
@Override
public
void
eventOccurred
(
Object
content
,
int
type
)
{
assert
type
==
EVENT_
ROAMING
_ENDED
;
assert
type
==
EVENT_
PAUSE
_ENDED
;
SimLocationActuator
comp
=
(
SimLocationActuator
)
content
;
this
.
addComponent
(
comp
);
}
private
long
getPauseTime
()
{
return
(
long
)
(
rnd
.
nextDouble
()
*
(
pauseTimeMax
-
pauseTimeMin
))
+
pauseTimeMin
;
}
public
void
setMinPauseTime
(
long
minPauseTime
)
{
if
(
minPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MinPauseTime should be >= 0!"
);
}
this
.
pauseTimeMin
=
minPauseTime
;
}
public
void
setMaxPauseTime
(
long
maxPauseTime
)
{
if
(
maxPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MaxPauseTime should be >= 0!"
);
}
this
.
pauseTimeMax
=
maxPauseTime
;
}
private
AttractionPoint
getNewAttractionPoint
(
SimLocationActuator
component
)
{
double
score
=
rnd
.
nextDouble
();
...
...
src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/SocialTransitionStrategy.java
View file @
d6e05af0
...
...
@@ -24,16 +24,13 @@ import java.util.ArrayList;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Random
;
import
java.util.Set
;
import
java.util.Vector
;
import
de.tud.kom.p2psim.api.common.SimHost
;
import
de.tud.kom.p2psim.api.common.SimHostComponent
;
import
de.tud.kom.p2psim.api.scenario.ConfigurationException
;
...
...
@@ -41,12 +38,10 @@ import de.tud.kom.p2psim.api.topology.Topology;
import
de.tud.kom.p2psim.api.topology.movement.SimLocationActuator
;
import
de.tud.kom.p2psim.api.topology.social.SocialView
;
import
de.tud.kom.p2psim.impl.simengine.Simulator
;
import
de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy.AttractionAssignmentListener
;
import
de.tud.kom.p2psim.impl.topology.util.PositionVector
;
import
de.tudarmstadt.maki.simonstrator.api.Binder
;
import
de.tudarmstadt.maki.simonstrator.api.Event
;
import
de.tudarmstadt.maki.simonstrator.api.EventHandler
;
import
de.tudarmstadt.maki.simonstrator.api.Randoms
;
import
de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint
;
/**
...
...
@@ -79,18 +74,13 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public
class
SocialTransitionStrategy
implements
ITransitionStrategy
,
EventHandler
{
public
class
SocialTransitionStrategy
extends
AbstractAttractionBasedTransitionStrategy
implements
EventHandler
{
private
String
socialId
=
null
;
private
SocialView
socialView
;
private
List
<
SimLocationActuator
>
comps
=
new
Vector
<
SimLocationActuator
>();
private
LinkedHashSet
<
AttractionPoint
>
aPoints
=
new
LinkedHashSet
<
AttractionPoint
>();
private
Map
<
SimLocationActuator
,
AttractionPoint
>
assignments
=
new
HashMap
<
SimLocationActuator
,
AttractionPoint
>();
private
List
<
SimLocationActuator
>
comps
=
new
Vector
<
SimLocationActuator
>();
private
Set
<
SimLocationActuator
>
arrivedAtAttractionPoint
=
new
LinkedHashSet
<>();
...
...
@@ -100,8 +90,6 @@ public class SocialTransitionStrategy
private
Map
<
SimHost
,
SimLocationActuator
>
mapHostMs
=
new
HashMap
<
SimHost
,
SimLocationActuator
>();
private
List
<
AttractionAssignmentListener
>
listeners
=
new
LinkedList
<>();
private
double
minPauseTime
=
Simulator
.
MINUTE_UNIT
*
0.5
;
private
double
maxPauseTime
=
Simulator
.
MINUTE_UNIT
*
100
;
...
...
@@ -110,16 +98,10 @@ public class SocialTransitionStrategy
private
long
numberOfFavoritePlaces
=
4
;
private
Random
rand
;
private
PositionVector
worldDimension
;
private
boolean
init
=
false
;
public
SocialTransitionStrategy
()
{
this
.
rand
=
Randoms
.
getRandom
(
SocialTransitionStrategy
.
class
);
}
private
void
init
()
{
if
(!
init
)
{
if
(
socialId
==
null
)
{
...
...
@@ -150,35 +132,12 @@ public class SocialTransitionStrategy
this
.
socialId
=
socialId
;
}
@Override
public
AttractionPoint
getAssignment
(
SimLocationActuator
comp
)
{
return
assignments
.
get
(
comp
);
}
@Override
public
void
addAttractionAssignmentListener
(
AttractionAssignmentListener
listener
)
{
listeners
.
add
(
listener
);
}
@Override
public
void
removeAttractionAssignmentListener
(
AttractionAssignmentListener
listener
)
{
listeners
.
remove
(
listener
);
}
@Override
public
void
setAttractionPoints
(
Collection
<
AttractionPoint
>
attractionPoints
)
{
init
();
aPoints
.
addAll
(
attractionPoints
);
super
.
setAttractionPoints
(
attractionPoints
);
}
@Override
public
Set
<
AttractionPoint
>
getAllAttractionPoints
()
{
return
aPoints
;
}
@Override
public
void
addComponent
(
SimLocationActuator
ms
)
{
comps
.
add
(
ms
);
...
...
@@ -187,8 +146,8 @@ public class SocialTransitionStrategy
// position.
// TODO: needed? We do Transition as next, and this will delete the
// assignment..
AttractionPoint
nearest
=
aPoints
.
iterator
().
next
();
for
(
AttractionPoint
aPoint
:
aPoints
)
{
AttractionPoint
nearest
=
a
ttraction
Points
.
iterator
().
next
();
for
(
AttractionPoint
aPoint
:
a
ttraction
Points
)
{
if
(
nearest
.
distanceTo
(
ms
.
getRealPosition
())
>
aPoint
.
distanceTo
(
ms
.
getRealPosition
()))
{
nearest
=
aPoint
;
...
...
@@ -206,7 +165,7 @@ public class SocialTransitionStrategy
AttractionPoint
attractionPoint
)
{
arrivedAtAttractionPoint
.
remove
(
comp
);
assignments
.
put
(
comp
,
attractionPoint
);
listeners
.
forEach
(
listener
->
listener
.
updatedAttraction
Assignment
(
comp
,
attractionPoint
)
)
;
notifyListenersOf
Assignment
Update
(
comp
,
attractionPoint
);
}
@Override
...
...
@@ -222,23 +181,21 @@ public class SocialTransitionStrategy
List
<
AttractionPoint
>
apFriends
=
getFriendsPlaces
(
ms
);
List
<
AttractionPoint
>
apClusters
=
getClusterPlaces
(
ms
);
List
<
AttractionPoint
>
apRandom
=
getRandomPlaces
(
ms
,
(
int
)
Math
.
max
(
aPoints
.
size
()
*
0.2
,
5
));
(
int
)
Math
.
max
(
a
ttraction
Points
.
size
()
*
0.2
,
5
));
AttractionPoint
ap
=
null
;
if
(
r
a
nd
.
nextDouble
()
<
socialFactor
)
{
if
(
rnd
.
nextDouble
()
<
socialFactor
)
{
ap
=
findHighestScore
(
ms
,
apFavorites
,
apFriends
,
apClusters
,
apRandom
);
}
else
{
List
<
AttractionPoint
>
aps
=
new
ArrayList
<
AttractionPoint
>();
aps
.
addAll
(
apRandom
);
aps
.
addAll
(
apFavorites
);
ap
=
aps
.
get
(
r
a
nd
.
nextInt
(
apRandom
.
size
()));
ap
=
aps
.
get
(
rnd
.
nextInt
(
apRandom
.
size
()));
}
assignments
.
put
(
ms
,
ap
);
arrivedAtAttractionPoint
.
remove
(
ms
);
for
(
AttractionAssignmentListener
listener
:
listeners
)
{
listener
.
updatedAttractionAssignment
(
ms
,
ap
);
}
notifyListenersOfAssignmentUpdate
(
ms
,
ap
);
}
private
AttractionPoint
findHighestScore
(
SimLocationActuator
ms
,
...
...
@@ -342,8 +299,8 @@ public class SocialTransitionStrategy
private
List
<
AttractionPoint
>
getRandomPlaces
(
SimLocationActuator
ms
,
int
number
)
{
List
<
AttractionPoint
>
result
=
new
Vector
<
AttractionPoint
>(
aPoints
);
Collections
.
shuffle
(
result
,
r
a
nd
);
List
<
AttractionPoint
>
result
=
new
Vector
<
AttractionPoint
>(
a
ttraction
Points
);
Collections
.
shuffle
(
result
,
rnd
);
return
result
.
subList
(
0
,
Math
.
min
(
result
.
size
(),
number
));
}
...
...
@@ -382,8 +339,8 @@ public class SocialTransitionStrategy
private
void
assignFavoritePlaces
(
SimLocationActuator
ms
)
{
Set
<
AttractionPoint
>
msFavoritePlaces
=
new
LinkedHashSet
<
AttractionPoint
>();
LinkedList
<
AttractionPoint
>
temp
=
new
LinkedList
<
AttractionPoint
>(
aPoints
);
Collections
.
shuffle
(
temp
,
r
a
nd
);
a
ttraction
Points
);
Collections
.
shuffle
(
temp
,
rnd
);
for
(
int
i
=
0
;
i
<
numberOfFavoritePlaces
;
i
++)
{
if
(!
temp
.
isEmpty
())
{
msFavoritePlaces
.
add
(
temp
.
removeFirst
());
...
...
@@ -401,28 +358,7 @@ public class SocialTransitionStrategy
mapHostMs
.
put
(
host
,
ms
);
mapMsHost
.
put
(
ms
,
host
);
}
protected
long
getPauseTime
()
{
return
(
long
)
((
rand
.
nextDouble
()
*
(
maxPauseTime
-
minPauseTime
))
+
minPauseTime
);
}
public
void
setMinPauseTime
(
long
minPauseTime
)
{
if
(
minPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MinPauseTime should be bigger then 0!"
);
}
this
.
minPauseTime
=
minPauseTime
;
}
public
void
setMaxPauseTime
(
long
maxPauseTime
)
{
if
(
maxPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MaxPauseTime should be bigger then 0!"
);
}
this
.
maxPauseTime
=
maxPauseTime
;
}
@Override
public
void
eventOccurred
(
Object
se
,
int
type
)
{
if
(
arrivedAtAttractionPoint
.
contains
(
se
))
{
...
...
src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/WeightedTransitionStrategy.java
View file @
d6e05af0
...
...
@@ -20,23 +20,11 @@
package
de.tud.kom.p2psim.impl.topology.movement.modularosm.transition
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Random
;
import
java.util.Set
;
import
org.joda.time.chrono.JulianChronology
;
import
de.tud.kom.p2psim.api.scenario.ConfigurationException
;
import
de.tud.kom.p2psim.api.topology.movement.SimLocationActuator
;
import
de.tudarmstadt.maki.simonstrator.api.Event
;
import
de.tudarmstadt.maki.simonstrator.api.EventHandler
;
import
de.tudarmstadt.maki.simonstrator.api.Randoms
;
import
de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint
;
/**
...
...
@@ -53,12 +41,6 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
*
*/
public
class
WeightedTransitionStrategy
extends
AbstractAttractionBasedTransitionStrategy
implements
EventHandler
{
private
long
pauseTimeMin
=
0
;
private
long
pauseTimeMax
=
0
;
private
final
static
int
EVENT_PAUSE_ENDED
=
1
;
@Override
public
void
addComponent
(
SimLocationActuator
ms
)
{
...
...
@@ -80,11 +62,7 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedTransitio
notifyListenersOfAssignmentUpdate
(
component
,
assignment
);
return
assignment
;
}
private
long
getPauseTime
(
SimLocationActuator
component
)
{
return
(
long
)
(
rnd
.
nextDouble
()
*
(
pauseTimeMax
-
pauseTimeMin
))
+
pauseTimeMin
;
}
@Override
public
void
eventOccurred
(
Object
content
,
int
type
)
{
assert
type
==
EVENT_PAUSE_ENDED
;
...
...
@@ -103,23 +81,7 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedTransitio
}
this
.
lastAssignments
.
put
(
ms
,
this
.
assignments
.
remove
(
ms
));
Event
.
scheduleWithDelay
(
getPauseTime
(
ms
),
this
,
ms
,
EVENT_PAUSE_ENDED
);
}
public
void
setMinPauseTime
(
long
minPauseTime
)
{
if
(
minPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MinPauseTime should be >= 0!"
);
}
this
.
pauseTimeMin
=
minPauseTime
;
}
public
void
setMaxPauseTime
(
long
maxPauseTime
)
{
if
(
maxPauseTime
<
0
)
{
throw
new
ConfigurationException
(
"MaxPauseTime should be >= 0!"
);
}
this
.
pauseTimeMax
=
maxPauseTime
;
Event
.
scheduleWithDelay
(
getPauseTime
(),
this
,
ms
,
EVENT_PAUSE_ENDED
);
}
}
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