// Path: src/main/java/epto/utils/Ball.java
// public class Ball extends HashMap<UUID, Event> {
// 
// }
// 
// Path: src/main/java/epto/utils/Event.java
// public class Event implements Comparable<Event>{
// 
//     public UUID id;
// 
//     public LogicalClock timestamp;
// 
//     public int ttl;
// 
//     public long sourceId;
// 
//     public Event() {
//         id = UUID.randomUUID();
//     }
// 
//     public int compareTo(Event o) {
//         int comparisionLC = timestamp.compareTo(o.timestamp);
//         return (comparisionLC != 0)? comparisionLC : (int)(sourceId - o.sourceId);
//     }
// 
//     @Override
//     public String toString() {
//         return "{timestamp=" + timestamp + ", ttl=" + ttl + ", sourceId=" + sourceId + "}";
//     }
// }
// 
// Path: src/main/java/epto/utils/Message.java
// public class Message {
// 
//     public final static int PREBROADCAST = 0;
//     public final static int BROADCAST = 1;
//     public final static int DELIVER = 2;
//     public final static int DISSEMINATION = 3;
//     public final static int ORDER = 4;
// 
//     private int type;
//     private Object content;
// //    private Node source;
// //    private Node destination;
// 
//     public Message(int type, Object content) {
//         this.type = type;
//         this.content = content;
//     }
// 
//     public int getType() {
//         return type;
//     }
// 
//     public void setType(int type) {
//         this.type = type;
//     }
// 
//     public Object getContent() {
//         return content;
//     }
// 
//     public void setContent(Object content) {
//         this.content = content;
//     }
// 
// //    public Node getSource() {
// //        return source;
// //    }
// //
// //    public void setSource(Node source) {
// //        this.source = source;
// //    }
// //
// //    public Node getDestination() {
// //        return destination;
// //    }
// //
// //    public void setDestination(Node destination) {
// //        this.destination = destination;
// //    }
// }
// 
// Path: src/main/java/epto/utils/Utils.java
// public class Utils {
// 
//     public static final int DEFAULT_FANOUT = 5;
// 
//     public static final int DEFAULT_TTL = 2;
// }
// 
// Path: src/main/java/pss/IPeerSamplingService.java
// public interface IPeerSamplingService {
// 
//     public Node selectNeighbor();
// 
//     public List<Node> selectNeighbors(int k);
// 
//     public int degree();
// 
//     public void myTurn(Node node, int pid);
// 
// }
// 
// Path: src/main/java/time/LogicalClock.java
// public class LogicalClock implements Comparable<LogicalClock> {
// 
//     private long nodeId;
//     private int eventId;
// 
//     public LogicalClock(long nodeId) {
//         this.nodeId = nodeId;
//         this.eventId = 0;
//     }
// 
//     public LogicalClock(long nodeId, int eventId) {
//         this(nodeId);
//         this.eventId = eventId;
//     }
// 
//     public void increment() {
//         this.eventId++;
//     }
// 
//     public long getNodeId() {
//         return nodeId;
//     }
// 
//     public void setNodeId(long nodeId) {
//         this.nodeId = nodeId;
//     }
// 
//     public int getEventId() {
//         return eventId;
//     }
// 
//     public void setEventId(int eventId) {
//         this.eventId = eventId;
//     }
// 
//     public int compareTo(LogicalClock o) {
//         return (nodeId == o.nodeId)? eventId - o.eventId : (int) nodeId - (int) o.nodeId;
//     }
// 
//     @Override
//     public String toString() {
//         return "{nodeId=" + nodeId + ", eventId=" + eventId + "}";
//     }
// 
//     @Override
//     public LogicalClock clone() throws CloneNotSupportedException {
//         return new LogicalClock(nodeId, eventId);
//     }
// }


import epto.utils.Ball;
import epto.utils.Event;
import epto.utils.Message;
import epto.utils.Utils;
import peersim.cdsim.CDProtocol;
import peersim.config.Configuration;
import peersim.config.FastConfig;
import peersim.core.Node;
import peersim.edsim.EDProtocol;
import peersim.transport.Transport;
import pss.IPeerSamplingService;
import time.LogicalClock;
import java.util.List;
package epto;




/**
 * The EpTO dissemination component
 *
 * The algorithm assumes the existence of a peer sampling service (PSS) responsible for keeping p’s view
 * up-to-date with a random stream of at least K deemed correct processes allowing a fanout of size K.
 * TTL (time to live) holds the number of rounds for which each event needs to be relayed during its dissemination.
 * The nextBall set collects the events to be sent in the next round by process p.
 * The dissemination component consists of three procedures executed atomically: the event broadcast primitive,
 * the event receive callback and the periodic relaying task.
 */
public class EpTODissemination implements CDProtocol, EDProtocol, EpTOBroadcaster {

    // =================================
    //  Configuration Parameters
    // =================================

    /**
     * Config parameter name for the fanout K: number of deemed correct processes
     * @config
     */
    private static final String PAR_FANOUT = "fanout";

    /**
     * Config parameter name for the TTL (time to live).
     * It is a constant holding the number of rounds for which each event needs to be relayed during its dissemination.
     * @config
     */
    private static final String PAR_TTL = "ttl";

    // =================================
    //  Parameters
    // =================================

    /**
     * The id of this protocol in the protocol array
     */
    public static int PID = 0;

    /**
     * The number of deemed correct processes
     */
    private final int K;

    /**
     * The number of rounds for which each event needs to be relayed during its dissemination
     */
    private final int TTL;

    /**
     * The nextBall set collects the events to be sent in the next round by process p
     * It relies on an HashMap<UUID, Event>
     */
    private Ball nextBall = new Ball();

    /**
     * Last updated LogicalClock
     */
    private LogicalClock lastLogicalClock;

    // =================================
    //  Constructor implementation
    // =================================

    public EpTODissemination(String prefix) {

        PID = Configuration.lookupPid(prefix.replace("protocol.",""));
        K = Configuration.getInt(prefix + "." + PAR_FANOUT, Utils.DEFAULT_FANOUT);
// Path: src/main/java/epto/utils/Ball.java
// public class Ball extends HashMap<UUID, Event> {
// 
// }
// 
// Path: src/main/java/epto/utils/Event.java
// public class Event implements Comparable<Event>{
// 
//     public UUID id;
// 
//     public LogicalClock timestamp;
// 
//     public int ttl;
// 
//     public long sourceId;
// 
//     public Event() {
//         id = UUID.randomUUID();
//     }
// 
//     public int compareTo(Event o) {
//         int comparisionLC = timestamp.compareTo(o.timestamp);
//         return (comparisionLC != 0)? comparisionLC : (int)(sourceId - o.sourceId);
//     }
// 
//     @Override
//     public String toString() {
//         return "{timestamp=" + timestamp + ", ttl=" + ttl + ", sourceId=" + sourceId + "}";
//     }
// }
// 
// Path: src/main/java/epto/utils/Message.java
// public class Message {
// 
//     public final static int PREBROADCAST = 0;
//     public final static int BROADCAST = 1;
//     public final static int DELIVER = 2;
//     public final static int DISSEMINATION = 3;
//     public final static int ORDER = 4;
// 
//     private int type;
//     private Object content;
// //    private Node source;
// //    private Node destination;
// 
//     public Message(int type, Object content) {
//         this.type = type;
//         this.content = content;
//     }
// 
//     public int getType() {
//         return type;
//     }
// 
//     public void setType(int type) {
//         this.type = type;
//     }
// 
//     public Object getContent() {
//         return content;
//     }
// 
//     public void setContent(Object content) {
//         this.content = content;
//     }
// 
// //    public Node getSource() {
// //        return source;
// //    }
// //
// //    public void setSource(Node source) {
// //        this.source = source;
// //    }
// //
// //    public Node getDestination() {
// //        return destination;
// //    }
// //
// //    public void setDestination(Node destination) {
// //        this.destination = destination;
// //    }
// }
// 
// Path: src/main/java/epto/utils/Utils.java
// public class Utils {
// 
//     public static final int DEFAULT_FANOUT = 5;
// 
//     public static final int DEFAULT_TTL = 2;
// }
// 
// Path: src/main/java/pss/IPeerSamplingService.java
// public interface IPeerSamplingService {
// 
//     public Node selectNeighbor();
// 
//     public List<Node> selectNeighbors(int k);
// 
//     public int degree();
// 
//     public void myTurn(Node node, int pid);
// 
// }
// 
// Path: src/main/java/time/LogicalClock.java
// public class LogicalClock implements Comparable<LogicalClock> {
// 
//     private long nodeId;
//     private int eventId;
// 
//     public LogicalClock(long nodeId) {
//         this.nodeId = nodeId;
//         this.eventId = 0;
//     }
// 
//     public LogicalClock(long nodeId, int eventId) {
//         this(nodeId);
//         this.eventId = eventId;
//     }
// 
//     public void increment() {
//         this.eventId++;
//     }
// 
//     public long getNodeId() {
//         return nodeId;
//     }
// 
//     public void setNodeId(long nodeId) {
//         this.nodeId = nodeId;
//     }
// 
//     public int getEventId() {
//         return eventId;
//     }
// 
//     public void setEventId(int eventId) {
//         this.eventId = eventId;
//     }
// 
//     public int compareTo(LogicalClock o) {
//         return (nodeId == o.nodeId)? eventId - o.eventId : (int) nodeId - (int) o.nodeId;
//     }
// 
//     @Override
//     public String toString() {
//         return "{nodeId=" + nodeId + ", eventId=" + eventId + "}";
//     }
// 
//     @Override
//     public LogicalClock clone() throws CloneNotSupportedException {
//         return new LogicalClock(nodeId, eventId);
//     }
// }


// Path: src/main/java/epto/EpTODissemination.java
import epto.utils.Ball;
import epto.utils.Event;
import epto.utils.Message;
import epto.utils.Utils;
import peersim.cdsim.CDProtocol;
import peersim.config.Configuration;
import peersim.config.FastConfig;
import peersim.core.Node;
import peersim.edsim.EDProtocol;
import peersim.transport.Transport;
import pss.IPeerSamplingService;
import time.LogicalClock;
import java.util.List;

package epto;




/**
 * The EpTO dissemination component
 *
 * The algorithm assumes the existence of a peer sampling service (PSS) responsible for keeping p’s view
 * up-to-date with a random stream of at least K deemed correct processes allowing a fanout of size K.
 * TTL (time to live) holds the number of rounds for which each event needs to be relayed during its dissemination.
 * The nextBall set collects the events to be sent in the next round by process p.
 * The dissemination component consists of three procedures executed atomically: the event broadcast primitive,
 * the event receive callback and the periodic relaying task.
 */
public class EpTODissemination implements CDProtocol, EDProtocol, EpTOBroadcaster {

    // =================================
    //  Configuration Parameters
    // =================================

    /**
     * Config parameter name for the fanout K: number of deemed correct processes
     * @config
     */
    private static final String PAR_FANOUT = "fanout";

    /**
     * Config parameter name for the TTL (time to live).
     * It is a constant holding the number of rounds for which each event needs to be relayed during its dissemination.
     * @config
     */
    private static final String PAR_TTL = "ttl";

    // =================================
    //  Parameters
    // =================================

    /**
     * The id of this protocol in the protocol array
     */
    public static int PID = 0;

    /**
     * The number of deemed correct processes
     */
    private final int K;

    /**
     * The number of rounds for which each event needs to be relayed during its dissemination
     */
    private final int TTL;

    /**
     * The nextBall set collects the events to be sent in the next round by process p
     * It relies on an HashMap<UUID, Event>
     */
    private Ball nextBall = new Ball();

    /**
     * Last updated LogicalClock
     */
    private LogicalClock lastLogicalClock;

    // =================================
    //  Constructor implementation
    // =================================

    public EpTODissemination(String prefix) {

        PID = Configuration.lookupPid(prefix.replace("protocol.",""));
        K = Configuration.getInt(prefix + "." + PAR_FANOUT, Utils.DEFAULT_FANOUT);
        TTL = Configuration.getInt(prefix + "." + PAR_TTL, Utils.DEFAULT_TTL);