samedi 20 juin 2020

How do I implement this state pattern design in java?

I am new to Java and Java Design patterns. I am working on project that implements state design pattern with simple factory design pattern. I am supposed to calculate The average popularity score of all videos contained in the channel.

Formula to calculate popularity score

(no. of views + 2 * (no. of likes - no. of dislikes)) / total no. of videos in the channel

Following are the states:


 1. Unpopular : Initial state. For channel to be in this state its popularity score should be between 0 and 1000
 2. MildlyPopular : For channel to be in this state its popularity score should be between 1000 and 10000
 3. HighlyPopular : For channel to be in this state its popularity score should be between 10000 and 100000
 4. UltraPopular : For channel to be in this state its popularity score should be between 100000 and INT_MAX.

Following are the Operations/Behaviors:


 1. ADD_VIDEO::<video name> to Add Video 
 2. REMOVE_VIDEO::<video name> to Remove Video
 3. METRICS__<video name>::[VIEWS=<no. of views>,LIKES=<no. of likes>,DISLIKES=<no. of dislikes>]

Input : input.txt

ADD_VIDEO::video1
ADD_VIDEO::video2
METRICS__video1::[VIEWS=1000,LIKES=20,DISLIKES=20]
METRICS__video2::[VIEWS=2000,LIKES=400,DISLIKES=20]
METRICS__video1::[VIEWS=20000,LIKES=1000,DISLIKES=-10]
METRICS__video2::[VIEWS=50,LIKES=-50,DISLIKES=0]
REMOVE_VIDEO::video2
ADD_VIDEO::video3
METRICS__video3::[VIEWS=2000,LIKES=100,DISLIKES=20]
METRICS__video1::[VIEWS=0,LIKES=-1000,DISLIKES=500]
ADD_VIDEO::video4
METRICS__video4::[VIEWS=100,LIKES=5,DISLIKES=0]
REMOVE_VIDEO::video1
REMOVE_VIDEO::video3

Output expected:

UNPOPULAR__VIDEO_ADDED::video1
UNPOPULAR__VIDEO_ADDED::video2
UNPOPULAR__POPULARITY_SCORE_UPDATE::500
UNPOPULAR__POPULARITY_SCORE_UPDATE::1880
MILDLY_POPULAR__POPULARITY_SCORE_UPDATE::12890
HIGHLY_POPULAR__POPULARITY_SCORE_UPDATE::12865
HIGHLY_POPULAR__VIDEO_REMOVED::video2
HIGHLY_POPULAR__VIDEO_ADDED::video3
HIGHLY_POPULAR__POPULARITY_SCORE_UPDATE::12590
HIGHLY_POPULAR__POPULARITY_SCORE_UPDATE::11090
HIGHLY_POPULAR__VIDEO_ADDED::video4
MILDLY_POPULAR__POPULARITY_SCORE_UPDATE::7430
MILDLY_POPULAR__VIDEO_REMOVED::video1
MILDLY_POPULAR__VIDEO_REMOVED::video3
UNPOPULAR__VIDEO_REMOVED::video4

So far I have managed to implement the following:

Main.java

public class Main {
    private static final int REQUIRED_NUMBER_OF_CMDLINE_ARGS = 2;

    public static void main(String[] args) throws Exception {
        if ((args.length != 2) || (args[0].equals("${input}")) || (args[1].equals("${output}"))) {
            System.err.printf("Error: Incorrect number of arguments. Program accepts %d arguments.", REQUIRED_NUMBER_OF_CMDLINE_ARGS);
            System.exit(0);
        }
        System.out.println("Hello World! Lets get started with the assignment");
FileProcessor readInputFile;

        readInputFile = new FileProcessor(args[0]);
        String line = null;

        while(null != (line = readInputFile.poll())) {
            String lines[] = line.split("::");
            System.out.println(lines[0]);
            System.out.println(lines[1]);
        }

    }
}

ChannelContext.java

public class ChannelContext {
    private StateI currentState;

    private Map<StateName, StateI> availableStates;

    public ChannelContext(SimpleStateFactoryI stateFactoryIn, List<StateName> stateNames) {
        for(StateName states : stateNames) {
            availableStates.put(states,stateFactoryIn.create(states));
        }
        setCurrentState(StateName.UNPOPULAR);
    }

    public void setCurrentState(StateName nextState) {
        if(availableStates.containsKey(nextState)) {
            currentState = availableStates.get(nextState);
        }
    }
}

StateI.java

public interface StateI {
    public void addVideo();
    public void removeVideo();
    public void Metrics();
}

UnpopularState.java and other states have following representation

public class UnpopularState implements StateI {

    @Override
    public void addVideo() {
       
    }

    @Override
    public void removeVideo() {
        
    }

    @Override
    public void calculateMetrics() {
        
    }

}

SimpleStateFactoryI.java

public interface SimpleStateFactoryI {
    public StateI create(StateName state);
}

SimpleStateFactory.java

public class SimpleStateFactory implements SimpleStateFactoryI {
    @Override
    public StateI create(StateName stateE) {
        StateI state = null;
        if(stateE == StateName.UNPOPULAR){
            state = new UnpopularState();
        }
        else if(stateE == StateName.MILDLY_POPULAR) {
            state = new MildlyPopularState();
        }
        else if(stateE == StateName.HIGHLY_POPULAR) {
            state = new HighlyPopularState();
        }
        else if(stateE == StateName.ULTRA_POPULAR) {
            state = new UltraPopularState();
        }
        return state;
    }
}

Operation.java enum file

public enum Operation {
    ADD_VIDEO, REMOVE_VIDEO, METRICS
}

StateName.java enum file

public enum StateName {
    UNPOPULAR, MILDLY_POPULAR, HIGHLY_POPULAR, ULTRA_POPULAR
}

Note

The context should use the simple factory design pattern to fetch the required state. 
The constructor of the context accepts an instance of SimpleStateFactory.
The create(...) method of SimpleStateFactory accepts an enum representing the state to be instantiated.
The setCurrentState(...) method of the context accepts an enum representing the state to change to. This is provided to the SimpleStateFactory instance to fetch an instance of the respective state.

Can anyone help me with the input parsing and storing it in data structures for further processing and calculations?

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire