Witam,
mam takie dość ciekawe zadanie do wykonania. Mianowicie:
- Mam jednego EJB opisanego interfejsem (więc go nie da rady ruszyć) - inicjuje grę i sprawdza czy podany wynik jest poprawny
- Mam drugiego EJB, który powinien wykonać algorytm rozwiązania gry MasterMind dla 5 kolumn i 8 kolorów.
- Mam servlet, który inicjuje grę (przez pierwszy EJB) po czym ją uruchamia (drugi EJB) i zwraca wynik.
Problem jest taki, że do wykonania algorytmu (algorytm Knutha), potrzebuje wiedzy: ile kulek było ułożonych dobrze oraz ile kolorów się pokryło. Tą wiedzę oferuje pierwszy EJB. Problemem jest - co zrobić żeby móc z niego korzystać?
Podanie go przez setera czy zrobienie z niego publicznego argumentu odpada, bo nie zgadza się na to interfejs (mam wymuszone, że ma się składać z jednej bez argumentowej metody - więc zrobienie funkcji rekurencyjnej też odpada). EJB nie może mieć też konstruktora z argumentami, więc i ta metoda odpada.
Po prostu jeden EJB musi jakoś znaleźć drugi. Oba są w jednym projekcie w jednej paczce.
Jeżeli może to pomóc, to rzucam kod:
Pierwszy EJB (GameMonitor) - tutaj jest bardzo przykładowy, bo przy ostatecznym rozwiązaniu ten skrypt zostanie podany odgórnie, stąd nie mam na niego w ogóle wpływu.
package game;
import java.util.Arrays;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Stateful
public class GameMonitor implements IGameMonitor{
private String goodCombination;
@Override
public boolean register(int hwork, String album) {
try {
return true;
} catch (Exception e) {
return false;
}
}
@Override
public void initGame(String state) {
goodCombination = state;
}
@Override
public String verify(String state) {
int colorOK = 0;
int allOK = 0;
char[] st = state.toCharArray();
char[] gc = goodCombination.toCharArray();
for(int i = 0 ; i < 5 ; i++) {
if(st[i] == gc[i]) {
allOK++;
continue;
}
if(Arrays.asList(gc).contains(st[i])) {
colorOK++;
}
}
String result = allOK + "" + colorOK;
return result;
}
}
Drugi EJB (MasterMind) ktory wykonuję samą grę. W nim potrzebuje poprzedniego EJB, ale nie mogę go zaimportować. Próbowałem już na masę różnych sposobów. Ten zaprezentowany tutaj, powoduje NullPointer.
package game;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.PersistenceContext;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Stateful
public class MasterMind implements IMasterMind{
@Override
public String playGame() {
int steps = 0;
try {
String attempt = "AABBB";
ArrayList<String> possibleGuess = createPossibleGuessArray("", "ABCDEFGH");
ArrayList<String> bestGuess = new ArrayList<String>();
String result = "00";
//Context context = new InitialContext();
//IGameMonitor gameMonitor = (IGameMonitor) context.lookup("java:global/ejb-project/IGameMonitor!pl.jrj.game.IGameMonitor");
IGameMonitor gameMonitor = (IGameMonitor) context.lookup(IGameMonitor.class.getName());
do {
if(steps == 0) {
// Pierwsza proba
attempt = "AABBB";
} else if(possibleGuess.size() == 1) {
// Ostatnia opcja
attempt = possibleGuess.get(0);
} else {
// usuwamy z tablicy poprzedni strzal
possibleGuess.remove(attempt);
ArrayList<Integer> tmpRemoveList = new ArrayList<>();
// usuwamy wszystkie, ktore dalyby podobny rezultat
for(int i = 0 ; i < possibleGuess.size() ; i++) {
int goodPin = 0;
int goodColor = 0;
for(int pin = 0 ; pin < 5 ; pin++) {
if(possibleGuess.get(i).charAt(pin) == attempt.charAt(pin)) {
goodPin++;
} else if(possibleGuess.get(i).contains("" + attempt.charAt(pin))) {
goodColor++;
}
}
if(goodPin != result.charAt(0) && goodColor != result.charAt(1)) {
tmpRemoveList.add(i);
}
}
for(int i : tmpRemoveList) {
possibleGuess.remove(i);
}
// Wybireamy kolejny krok, szukajac opcji, ktora wyeliminuje najwiecej opcji
int maxMin = 0;
for(int i = 0 ; i < possibleGuess.size() ; i++) {
int min = Integer.MAX_VALUE;
int goodPin = 0;
int goodColor = 0;
for(int pin = 0 ; pin < 5 ; pin++) {
if(possibleGuess.get(i).charAt(pin) == attempt.charAt(pin)) {
goodPin++;
} else if(possibleGuess.get(i).contains("" + attempt.charAt(pin))) {
goodColor++;
}
}
if(goodPin != result.charAt(0) && goodColor != result.charAt(1)) {
min++;
}
if(min == maxMin && min > 0) {
bestGuess.add(possibleGuess.get(i));
}
if(min > maxMin) {
maxMin = min;
bestGuess.clear();
bestGuess.add(possibleGuess.get(i));
}
}
attempt = bestGuess.get(0);
}
result = gameMonitor.verify(attempt);
steps++;
} while (!result.equals("50"));
//} catch (NamingException ex) {
// return ex + " - " + ex.getCause();
} catch (Exception ex) {
return ex + " - " + ex.getCause();
}
return "" + steps;
}
private ArrayList<String> createPossibleGuessArray(String prefix, String str)
{
ArrayList<String> possibleGuess = new ArrayList<>();
int n = str.length();
if (n == 0) {
possibleGuess.add(prefix);
} else {
for (int i = 0; i < n; i++) {
possibleGuess.addAll(createPossibleGuessArray(prefix + str.charAt(i), str.substring(i + 1, n) + str.substring(0, i)));
}
}
return possibleGuess;
}
}
Servlet (MGame), realizuje grę. W nim oba EJB wstrzyknięte są prawidłowo i bez problemów.
public class MGame extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String steps = "";
PrintWriter out = response.getWriter();
try {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
Context context = new InitialContext();
//IGameMonitor gameMonitor = (IGameMonitor) context.lookup("java:global/ejb-project/IGameMonitor!pl.jrj.game.IGameMonitor");
IGameMonitor gameMonitor = (IGameMonitor) context.lookup(IGameMonitor.class.getName());
//IMasterMind masterMind = (IMasterMind) context.lookup("java:global/ejb-project/IMasterMind!pl.jrj.game.IMasterMind");
IMasterMind masterMind = (IMasterMind) context.lookup(IMasterMind.class.getName());
Map<String, String> messages = new HashMap<>();
request.setAttribute("messages", messages);
String m = request.getParameter("m");
//MasterMind masterMind = new MasterMind();
if(gameMonitor.register(5, "98142")) {
gameMonitor.initGame(m);
steps = masterMind.playGame();
}
out.println(steps);
} catch (NamingException ex) {
out.println(ex);
} catch (Exception ex) {
out.println(ex);
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
Jakieś pomysły co zrobić, żeby to zadziałało?