text:
package actors

import com.cave.metrics.data._
import init.AwsWrapper.WorkItem
import org.mockito.Mockito
import org.mockito.Mockito._
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{BeforeAndAfter, FlatSpec}
import org.specs2.matcher.ShouldMatchers
import play.api.libs.json.Json

import scala.util.{Failure, Success}

class CoordinatorCacheSpec extends FlatSpec with ShouldMatchers with MockitoSugar with BeforeAndAfter with AlertJsonData {

  val mockDataManager = mock[CacheDataManager]
  val mockListener = mock[CoordinatorCacheListener]

  val ItemId = "12345"
  val ReceiptHandle = "RecHandle12345"
  val NewUrl = "http://new.url/"

  before {
    Mockito.reset(mockDataManager, mockListener)
  }

  "CoordinatorCache" should "create an empty list for a new org" in {

    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map.empty[String, List[Schedule]]))
    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(0)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Organization, Operation.Create, OrgName, "")))
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "log a warning if it receives a create event for known organization" in {
    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Organization, Operation.Create, OrgName, "")))
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "send new url to listener when org updated" in {

    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Organization, Operation.Update, OrgName, NewUrl)))
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).notifyUrlChange(SomeId, NewUrl)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "log a warning if it receives an update event for unknown organization" in {

    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map.empty[String, List[Schedule]]))
    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(0)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Organization, Operation.Update, OrgName, NotificationUrl)))
    cache.schedulesByOrganization should haveSize(0)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "delete all alerts when their org is deleted" in {
    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    val OtherId = "4321"
    val OtherSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(OtherId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule, OtherSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(2)
    verify(mockListener).createScheduler(SomeSchedule)
    verify(mockListener).createScheduler(OtherSchedule)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Organization, Operation.Delete, OrgName, "")))
    cache.schedulesByOrganization should haveSize(0)
    verify(mockListener).stopScheduler(SomeId)
    verify(mockListener).stopScheduler(OtherId)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "log a warning if it receives a delete event for unknown organization" in {

    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map.empty[String, List[Schedule]]))
    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(0)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Organization, Operation.Delete, OrgName, "")))
    cache.schedulesByOrganization should haveSize(0)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "add a new alert when it receives a create alert event and alert is enabled" in {

    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    val OtherId = "4321"
    val OtherSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(OtherId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Create, OtherId, Json.stringify(Json.toJson(OtherSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(2)
    verify(mockListener).createScheduler(OtherSchedule)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)

  }

  it should "ignore a new alert when it receives a create alert event and alert is disabled" in {

    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List())))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)

    val OtherId = "4321"
    val OtherSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(OtherId), AlertDescription, AlertDisabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Create, OtherId, Json.stringify(Json.toJson(OtherSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)

  }

  it should "log a warning and skip a duplicate create alert event" in {
    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    val OtherSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), OtherAlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Create, SomeId, Json.stringify(Json.toJson(OtherSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)

  }

  it should "stop and recreate a scheduler when an alert is updated" in {

    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    val NewSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), OtherAlertDescription, OtherAlertEnabled, OtherAlertPeriod, OtherAlertCondition, Some(AlertHandbookUrl), Some(OtherAlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Update, SomeId, Json.stringify(Json.toJson(NewSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).stopScheduler(SomeId)
    verify(mockListener).createScheduler(NewSchedule)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "stop but not recreate a scheduler when an alert is updated and disabled" in {

    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    val NewSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), OtherAlertDescription, AlertDisabled, OtherAlertPeriod, OtherAlertCondition, Some(OtherAlertHandbookUrl), Some(OtherAlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Update, SomeId, Json.stringify(Json.toJson(NewSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)
    verify(mockListener).stopScheduler(SomeId)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "log a warning but skip an alert update that can't be parsed" in {
    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    val NewSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), OtherAlertDescription, OtherAlertEnabled, OtherAlertPeriod, OtherAlertCondition, Some(OtherAlertHandbookUrl), Some(OtherAlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Update, SomeId, "Boom!")))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "create an alert when it receives an update for a previously disabled alert" in {
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List())))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)

    val OtherId = "4321"
    val OtherSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(OtherId), OtherAlertDescription, OtherAlertEnabled, OtherAlertPeriod, OtherAlertCondition, Some(OtherAlertHandbookUrl), Some(OtherAlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Update, OtherId, Json.stringify(Json.toJson(OtherSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(OtherSchedule)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)

  }

  it should "ignore an alert when it receives an update for a previously disabled alert that remains disabled" in {
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List())))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)

    val OtherId = "4321"
    val OtherSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(OtherId), OtherAlertDescription, AlertDisabled, OtherAlertPeriod, OtherAlertCondition, Some(OtherAlertHandbookUrl), Some(OtherAlertRouting)))
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Update, OtherId, Json.stringify(Json.toJson(OtherSchedule)))))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)

  }

  it should "stop the scheduler when an alert is deleted" in {
    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Delete, SomeId, OrgName)))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)
    verify(mockListener).stopScheduler(SomeId)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "log a warning but skip an alert delete for an unknown alert id" in {
    val SomeId = "1234"
    val SomeSchedule = Schedule(OrgName, Some(TeamName), None, NotificationUrl, Alert(Some(SomeId), AlertDescription, AlertEnabled, AlertPeriod, AlertCondition, Some(AlertHandbookUrl), Some(AlertRouting)))
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map(OrgName -> List(SomeSchedule))))

    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(1)
    verify(mockListener).createScheduler(SomeSchedule)

    val OtherId = "4321"
    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Alert, Operation.Delete, OtherId, OrgName)))

    cache.schedulesByOrganization should haveSize(1)
    cache.schedulesByOrganization(OrgName) should haveSize(0)

    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

  it should "throw exception if it cannot read the initial list from database" in {
    when(mockDataManager.getEnabledAlerts()).thenReturn(Failure(new RuntimeException("Boom!")))
    intercept[RuntimeException] {
      new CoordinatorCache(mockDataManager, mockListener)
    }
  }

  it should "log a message but skip an update it doesn't support" in {
    when(mockDataManager.getEnabledAlerts()).thenReturn(Success(Map.empty[String, List[Schedule]]))
    val cache = new CoordinatorCache(mockDataManager, mockListener)
    cache.schedulesByOrganization should haveSize(0)

    cache.updateCache(WorkItem(ItemId, ReceiptHandle, Update(Entity.Team, Operation.Create, OrgName, "")))
    cache.schedulesByOrganization should haveSize(0)
    verify(mockListener).deleteMessage(ReceiptHandle)

    verifyNoMoreInteractions(mockListener)
  }

}


text:
echo "WMBR Transmitter Sensor Logger starting up..."
echo
echo "Setting system time"
# Our server has no internal clock, so we set it at startup
rm /etc/localtime
ln -s /usr/share/zoneinfo/America/New_York /etc/localtime
ntpdate pool.ntp.org

echo
echo "Starting logger"
python ~/transmittr/main.py &

echo
echo "Starting web server"
# Make sure the bonescript service isn't trying to hog port 80
systemctl disable bonescript.socket
systemctl disable bonescript.service
systemctl disable bonescript-autorun.service
systemctl stop bonescript.socket
systemctl stop bonescript.service
systemctl stop bonescript-autorun.service

echo
echo "No server available yet..."

redpajama_set_name: RedPajamaGithub


text:
@class HistoryOverlayView;

enum HistoryOverlayMode {
  kHistoryOverlayModeBack,
  kHistoryOverlayModeForward
};

// The HistoryOverlayController manages a view that is inserted atop the web
// contents to provide visual feedback when the user is performing history
// navigation gestures.
@interface HistoryOverlayController : NSViewController {
 @private
  HistoryOverlayMode mode_;
  // Strongly typed reference of self.view.
  base::scoped_nsobject<HistoryOverlayView> contentView_;
  // The view above which self.view is inserted as a subview.
  base::scoped_nsobject<NSView> parent_;
}

// Designated initializer.
- (id)initForMode:(HistoryOverlayMode)mode;

// Shows the shield above |view|.
- (void)showPanelForView:(NSView*)view;

// Updates the appearance of the overlay based on track gesture progress.
- (void)setProgress:(CGFloat)gestureAmount;

// Fades the shield out and removes it from the view hierarchy.
- (void)dismiss;

@end

#endif  // CHROME_BROWSER_UI_COCOA_OVERLAY_PANEL_CONTROLLER_H_


text:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package erp.mod.cfg.db;

import erp.mod.SModConsts;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import sa.gui.util.SUtilConsts;
import sa.lib.SLibUtils;
import sa.lib.db.SDbConsts;
import sa.lib.db.SDbRegistryUser;
import sa.lib.gui.SGuiSession;

/**
 *
 * @author Claudio Peña, Sergio Flores
 */
public class SDbShift extends SDbRegistryUser {

    protected int mnPkShiftId;
    protected String msCode;
    protected String msName;
    protected Date mtTimeStart;
    protected Date mtTimeEnd;
    /*
    protected boolean mbDeleted;
    protected boolean mbSystem;
    protected int mnFkUserInsertId;
    protected int mnFkUserUpdateId;
    protected Date mtTsUserInsert;
    protected Date mtTsUserUpdate;
    */

    public SDbShift() {
        super(SModConsts.CFGU_SHIFT);
    }

    public void setPkShiftId(int n) { mnPkShiftId = n; }
    public void setCode(String s) { msCode = s; }
    public void setName(String s) { msName = s; }
    public void setTimeStart(Date t) { mtTimeStart = t; }
    public void setTimeEnd(Date t) { mtTimeEnd = t; }
    public void setDeleted(boolean b) { mbDeleted = b; }
    public void setSystem(boolean b) { mbSystem = b; }
    public void setFkUserInsertId(int n) { mnFkUserInsertId = n; }
    public void setFkUserUpdateId(int n) { mnFkUserUpdateId = n; }
    public void setTsUserInsert(Date t) { mtTsUserInsert = t; }
    public void setTsUserUpdate(Date t) { mtTsUserUpdate = t; }

    public int getPkShiftId() { return mnPkShiftId; }
    public String getCode() { return msCode; }
    public String getName() { return msName; }
    public Date getTimeStart() { return mtTimeStart; }
    public Date getTimeEnd() { return mtTimeEnd; }
    public boolean isDeleted() { return mbDeleted; }
    public boolean isSystem() { return mbSystem; }
    public int getFkUserInsertId() { return mnFkUserInsertId; }
    public int getFkUserUpdateId() { return mnFkUserUpdateId; }
    public Date getTsUserInsert() { return mtTsUserInsert; }
    public Date getTsUserUpdate() { return mtTsUserUpdate; }

    @Override
    public void setPrimaryKey(int[] pk) {
        mnPkShiftId = pk[0];
    }

    @Override
    public int[] getPrimaryKey() {
        return new int[] { mnPkShiftId };
    }

    @Override
    public void initRegistry() {
        initBaseRegistry();

        mnPkShiftId = 0;
        msCode = "";
        msName = "";
        mtTimeStart = null;
        mtTimeEnd = null;
        mbDeleted = false;
        mbSystem = false;
        mnFkUserInsertId = 0;
        mnFkUserUpdateId = 0;
        mtTsUserInsert = null;
        mtTsUserUpdate = null;
    }

    @Override
    public String getSqlTable() {
        return SModConsts.TablesMap.get(mnRegistryType);
    }

    @Override
    public String getSqlWhere() {
        return "WHERE id_shift = " + mnPkShiftId + " ";
    }

    @Override
    public String getSqlWhere(int[] pk) {
        return "WHERE id_shift = " + pk[0] + " ";
    }

    @Override
    public void computePrimaryKey(SGuiSession session) throws SQLException, Exception {
        ResultSet resultSet = null;

        mnPkShiftId = 0;

        msSql = "SELECT COALESCE(MAX(id_shift), 0) + 1 FROM " + getSqlTable() + " ";
        resultSet = session.getStatement().executeQuery(msSql);
        if (resultSet.next()) {
            mnPkShiftId = resultSet.getInt(1);
        }
    }

    @Override
    public void read(SGuiSession session, int[] pk) throws SQLException, Exception {
        ResultSet resultSet = null;

        initRegistry();
        initQueryMembers();
        mnQueryResultId = SDbConsts.READ_ERROR;

        msSql = "SELECT * " + getSqlFromWhere(pk);
        resultSet = session.getStatement().executeQuery(msSql);
        if (!resultSet.next()) {
            throw new Exception(SDbConsts.ERR_MSG_REG_NOT_FOUND);
        }
        else {
            mnPkShiftId = resultSet.getInt("id_shift");
            msCode = resultSet.getString("code");
            msName = resultSet.getString("name");
            mtTimeStart = resultSet.getTime("time_sta");
            mtTimeEnd = resultSet.getTime("time_end");
            mbDeleted = resultSet.getBoolean("b_del");
            mbSystem = resultSet.getBoolean("b_sys");
            mnFkUserInsertId = resultSet.getInt("fk_usr_ins");
            mnFkUserUpdateId = resultSet.getInt("fk_usr_upd");
            mtTsUserInsert = resultSet.getTimestamp("ts_usr_ins");
            mtTsUserUpdate = resultSet.getTimestamp("ts_usr_upd");

            mbRegistryNew = false;
        }

        mnQueryResultId = SDbConsts.READ_OK;
    }

    @Override
    public void save(SGuiSession session) throws SQLException, Exception {
        initQueryMembers();
        mnQueryResultId = SDbConsts.SAVE_ERROR;

        if (mbRegistryNew) {
            computePrimaryKey(session);
            mbDeleted = false;
            mbSystem = false;
            mnFkUserInsertId = session.getUser().getPkUserId();
            mnFkUserUpdateId = SUtilConsts.USR_NA_ID;

            msSql = "INSERT INTO " + getSqlTable() + " VALUES (" +
                    mnPkShiftId + ", " +
                    "'" + msCode + "', " +
                    "'" + msName + "', " +
                    "'" + SLibUtils.DbmsDateFormatTime.format(mtTimeStart) + "', " +
                    "'" + SLibUtils.DbmsDateFormatTime.format(mtTimeEnd) + "', " +
                    (mbDeleted ? 1 : 0) + ", " +
                    (mbSystem ? 1 : 0) + ", " +
                    mnFkUserInsertId + ", " +
                    mnFkUserUpdateId + ", " +
                    "NOW()" + ", " +
                    "NOW()" + " " +
                    ")";
        }
        else {
            mnFkUserUpdateId = session.getUser().getPkUserId();

            msSql = "UPDATE " + getSqlTable() + " SET " +
                    //"id_shift = " + mnPkShiftId + ", " +
                    "code = '" + msCode + "', " +
                    "name = '" + msName + "', " +
                    "time_sta = '" + SLibUtils.DbmsDateFormatTime.format(mtTimeStart) + "', " +
                    "time_end = '" + SLibUtils.DbmsDateFormatTime.format(mtTimeEnd) + "', " +
                    "b_del = " + (mbDeleted ? 1 : 0) + ", " +
                    "b_sys = " + (mbSystem ? 1 : 0) + ", " +
                    //"fk_usr_ins = " + mnFkUserInsertId + ", " +
                    "fk_usr_upd = " + mnFkUserUpdateId + ", " +
                    //"ts_usr_ins = " + "NOW()" + ", " +
                    "ts_usr_upd = " + "NOW()" + " " +
                    getSqlWhere();
        }

        session.getStatement().execute(msSql);
        mbRegistryNew = false;
        mnQueryResultId = SDbConsts.SAVE_OK;
    }

    @Override
    public SDbShift clone() throws CloneNotSupportedException {
        SDbShift registry = new SDbShift();

        registry.setPkShiftId(this.getPkShiftId());
        registry.setCode(this.getCode());
        registry.setName(this.getName());
        registry.setTimeStart(this.getTimeStart());
        registry.setTimeEnd(this.getTimeEnd());
        registry.setDeleted(this.isDeleted());
        registry.setSystem(this.isSystem());
        registry.setFkUserInsertId(this.getFkUserInsertId());
        registry.setFkUserUpdateId(this.getFkUserUpdateId());
        registry.setTsUserInsert(this.getTsUserInsert());
        registry.setTsUserUpdate(this.getTsUserUpdate());

        registry.setRegistryNew(this.isRegistryNew());
        return registry;
    }
}


text:
package com.stripe.android.model;

import com.stripe.android.util.DateUtils;
import com.stripe.android.util.TextUtils;

public class Card extends com.stripe.model.StripeObject {
    public static final String AMERICAN_EXPRESS = "American Express";
    public static final String DISCOVER = "Discover";
    public static final String JCB = "JCB";
    public static final String DINERS_CLUB = "Diners Club";
    public static final String VISA = "Visa";
    public static final String MASTERCARD = "MasterCard";
    public static final String UNKNOWN = "Unknown";

    // Based on http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29
    public static final String[] PREFIXES_AMERICAN_EXPRESS = {"34", "37"};
    public static final String[] PREFIXES_DISCOVER = {"60", "62", "64", "65"};
    public static final String[] PREFIXES_JCB = {"35"};
    public static final String[] PREFIXES_DINERS_CLUB = {"300", "301", "302", "303", "304", "305", "309", "36", "38", "37", "39"};
    public static final String[] PREFIXES_VISA = {"4"};
    public static final String[] PREFIXES_MASTERCARD = {"50", "51", "52", "53", "54", "55"};

    public static final int MAX_LENGTH_STANDARD = 16;
    public static final int MAX_LENGTH_AMERICAN_EXPRESS = 15;
    public static final int MAX_LENGTH_DINERS_CLUB = 14;

    private String number;
    private String cvc;
    private Integer expMonth;
    private Integer expYear;
    private String name;
    private String addressLine1;
    private String addressLine2;
    private String addressCity;
    private String addressState;
    private String addressZip;
    private String addressCountry;
    private String last4;
    private String type;
    private String fingerprint;
    private String country;

    public static class Builder {
        private final String number;
        private final String cvc;
        private final Integer expMonth;
        private final Integer expYear;
        private String name;
        private String addressLine1;
        private String addressLine2;
        private String addressCity;
        private String addressState;
        private String addressZip;
        private String addressCountry;
        private String last4;
        private String type;
        private String fingerprint;
        private String country;

        public Builder(String number, Integer expMonth, Integer expYear, String cvc) {
            this.number = number;
            this.expMonth = expMonth;
            this.expYear = expYear;
            this.cvc = cvc;
        }

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder addressLine1(String address) {
            this.addressLine1 = address;
            return this;
        }

        public Builder addressLine2(String address) {
            this.addressLine2 = address;
            return this;
        }

        public Builder addressCity(String city) {
            this.addressCity = city;
            return this;
        }

        public Builder addressState(String state) {
            this.addressState = state;
            return this;
        }

        public Builder addressZip(String zip) {
            this.addressZip = zip;
            return this;
        }

        public Builder addressCountry(String country) {
            this.addressCountry = country;
            return this;
        }

        public Builder last4(String last4) {
            this.last4 = last4;
            return this;
        }

        public Builder type(String type) {
            this.type = type;
            return this;
        }

        public Builder fingerprint(String fingerprint) {
            this.fingerprint = fingerprint;
            return this;
        }

        public Builder country(String country) {
            this.country = country;
            return this;
        }

        public Card build() {
            return new Card(this);
        }
    }

    private Card(Builder builder) {
        this.number = TextUtils.nullIfBlank(normalizeCardNumber(builder.number));
        this.expMonth = builder.expMonth;
        this.expYear = builder.expYear;
        this.cvc = TextUtils.nullIfBlank(builder.cvc);
        this.name = TextUtils.nullIfBlank(builder.name);
        this.addressLine1 = TextUtils.nullIfBlank(builder.addressLine1);
        this.addressLine2 = TextUtils.nullIfBlank(builder.addressLine2);
        this.addressCity = TextUtils.nullIfBlank(builder.addressCity);
        this.addressState = TextUtils.nullIfBlank(builder.addressState);
        this.addressZip = TextUtils.nullIfBlank(builder.addressZip);
        this.addressCountry = TextUtils.nullIfBlank(builder.addressCountry);
        this.last4 = TextUtils.nullIfBlank(builder.last4);
        this.type = TextUtils.nullIfBlank(builder.type);
        this.fingerprint = TextUtils.nullIfBlank(builder.fingerprint);
        this.country = TextUtils.nullIfBlank(builder.country);
        this.type = getType();
        this.last4 = getLast4();
    }

    public Card(String number, Integer expMonth, Integer expYear, String cvc, String name, String addressLine1, String addressLine2, String addressCity, String addressState, String addressZip, String addressCountry, String last4, String type, String fingerprint, String country) {
        this.number = TextUtils.nullIfBlank(normalizeCardNumber(number));
        this.expMonth = expMonth;
        this.expYear = expYear;
        this.cvc = TextUtils.nullIfBlank(cvc);
        this.name = TextUtils.nullIfBlank(name);
        this.addressLine1 = TextUtils.nullIfBlank(addressLine1);
        this.addressLine2 = TextUtils.nullIfBlank(addressLine2);
        this.addressCity = TextUtils.nullIfBlank(addressCity);
        this.addressState = TextUtils.nullIfBlank(addressState);
        this.addressZip = TextUtils.nullIfBlank(addressZip);
        this.addressCountry = TextUtils.nullIfBlank(addressCountry);
        this.last4 = TextUtils.nullIfBlank(last4);
        this.type = TextUtils.nullIfBlank(type);
        this.fingerprint = TextUtils.nullIfBlank(fingerprint);
        this.country = TextUtils.nullIfBlank(country);
        this.type = getType();
        this.last4 = getLast4();
    }

    public Card(String number, Integer expMonth, Integer expYear, String cvc, String name, String addressLine1, String addressLine2, String addressCity, String addressState, String addressZip, String addressCountry) {
        this(number, expMonth, expYear, cvc, name, addressLine1, addressLine2, addressCity, addressState, addressZip, addressCountry, null, null, null, null);
    }

    public Card(String number, Integer expMonth, Integer expYear, String cvc) {
        this(number, expMonth, expYear, cvc, null, null, null, null, null, null, null, null, null, null, null);
    }

    public boolean validateCard() {
        if (cvc == null) {
            return validateNumber() && validateExpiryDate();
        } else {
            return validateNumber() && validateExpiryDate() && validateCVC();
        }
    }

    public boolean validateNumber() {
        if (TextUtils.isBlank(number)) {
            return false;
        }

        String rawNumber = number.trim().replaceAll("\\s+|-", "");
        if (TextUtils.isBlank(rawNumber)
                || !TextUtils.isWholePositiveNumber(rawNumber)
                || !isValidLuhnNumber(rawNumber)) {
            return false;
        }

        if (AMERICAN_EXPRESS.equals(type)) {
            return rawNumber.length() == MAX_LENGTH_AMERICAN_EXPRESS;
        } else if (DINERS_CLUB.equals(type)) {
            return rawNumber.length() == MAX_LENGTH_DINERS_CLUB;
        } else {
            return rawNumber.length() == MAX_LENGTH_STANDARD;
        }
    }

    public boolean validateExpiryDate() {
    	if (!validateExpMonth()) {
    		return false;
    	}
    	if (!validateExpYear()) {
    		return false;
    	}
    	return !DateUtils.hasMonthPassed(expYear, expMonth);
    }

    public boolean validateExpMonth() {
    	if (expMonth == null) {
    		return false;
    	}
    	return (expMonth >= 1 && expMonth <= 12);
    }

    public boolean validateExpYear() {
    	if (expYear == null) {
    		return false;
    	}
    	return !DateUtils.hasYearPassed(expYear);
    }

    public boolean validateCVC() {
        if (TextUtils.isBlank(cvc)) {
            return false;
        }
        String cvcValue = cvc.trim();

        boolean validLength = ((type == null && cvcValue.length() >= 3 && cvcValue.length() <= 4) ||
                (AMERICAN_EXPRESS.equals(type) && cvcValue.length() == 4) ||
                (!AMERICAN_EXPRESS.equals(type) && cvcValue.length() == 3));

        if (!TextUtils.isWholePositiveNumber(cvcValue) || !validLength) {
            return false;
        }
        return true;
    }

    private boolean isValidLuhnNumber(String number) {
        boolean isOdd = true;
        int sum = 0;

        for (int index = number.length() - 1; index >= 0; index--) {
            char c = number.charAt(index);
            if (!Character.isDigit(c)) {
                return false;
            }
            int digitInteger = Integer.parseInt("" + c);
            isOdd = !isOdd;

            if (isOdd) {
                digitInteger *= 2;
            }

            if (digitInteger > 9) {
                digitInteger -= 9;
            }

            sum += digitInteger;
        }

        return sum % 10 == 0;
    }

    private String normalizeCardNumber(String number) {
        if (number == null) {
            return null;
        }
        return number.trim().replaceAll("\\s+|-", "");
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getCVC() {
        return cvc;
    }

    public void setCVC(String cvc) {
        this.cvc = cvc;
    }

    public Integer getExpMonth() {
        return expMonth;
    }

    public void setExpMonth(Integer expMonth) {
        this.expMonth = expMonth;
    }

    public Integer getExpYear() {
        return expYear;
    }

    public void setExpYear(Integer expYear) {
        this.expYear = expYear;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getAddressLine1() {
        return addressLine1;
    }

    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }

    public String getAddressLine2() {
        return addressLine2;
    }

    public void setAddressLine2(String addressLine2) {
        this.addressLine2 = addressLine2;
    }

    public String getAddressCity() {
        return addressCity;
    }

    public void setAddressCity(String addressCity) {
        this.addressCity = addressCity;
    }

    public String getAddressZip() {
        return addressZip;
    }

    public void setAddressZip(String addressZip) {
        this.addressZip = addressZip;
    }

    public String getAddressState() {
        return addressState;
    }

    public void setAddressState(String addressState) {
        this.addressState = addressState;
    }

    public String getAddressCountry() {
        return addressCountry;
    }

    public void setAddressCountry(String addressCountry) {
        this.addressCountry = addressCountry;
    }

    public String getLast4() {
        if (!TextUtils.isBlank(last4)) {
            return last4;
        }
        if (number != null && number.length() > 4) {
            return number.substring(number.length() - 4, number.length());
        }
        return null;
    }

    public String getType() {
        if (TextUtils.isBlank(type) && !TextUtils.isBlank(number)) {
            if (TextUtils.hasAnyPrefix(number, PREFIXES_AMERICAN_EXPRESS)) {
                return AMERICAN_EXPRESS;
            } else if (TextUtils.hasAnyPrefix(number, PREFIXES_DISCOVER)) {
                return DISCOVER;
            } else if (TextUtils.hasAnyPrefix(number, PREFIXES_JCB)) {
                return JCB;
            } else if (TextUtils.hasAnyPrefix(number, PREFIXES_DINERS_CLUB)) {
                return DINERS_CLUB;
            } else if (TextUtils.hasAnyPrefix(number, PREFIXES_VISA)) {
                return VISA;
            } else if (TextUtils.hasAnyPrefix(number, PREFIXES_MASTERCARD)) {
                return MASTERCARD;
            } else {
                return UNKNOWN;
            }
        }

        return type;
    }

    public String getFingerprint() {
        return fingerprint;
    }

    public String getCountry() {
        return country;
    }
}


text:
package net.unicon.cas.support.wsfederation.authentication.principal;

import net.unicon.cas.support.wsfederation.WsFederationConfiguration;
import org.jasig.cas.authentication.Credential;
import org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class resolves the principal id regarding the WsFederation credentials.
 *
 * @author John Gasper
 * @since 3.5.1
 */
public final class WsFederationCredentialsToPrincipalResolver extends PersonDirectoryPrincipalResolver {

    private final Logger logger = LoggerFactory.getLogger(WsFederationCredentialsToPrincipalResolver.class);

    private WsFederationConfiguration configuration;

    /**
     * Extracts the principalId.
     *
     * @param credentials the credentials
     * @return the principal id
     */
    @Override
    protected String extractPrincipalId(final Credential credentials) {

        final WsFederationCredential wsFedCredentials = (WsFederationCredential) credentials;
        final String principalId = wsFedCredentials.getAttributes().get(
                this.configuration.getIdentityAttribute()
        ).toString();
        logger.debug("principalId : {}", principalId);
        return principalId;
    }

    /**
     * Sets the configuration.
     *
     * @param configuration a configuration
     */
    public void setConfiguration(final WsFederationConfiguration configuration) {
        this.configuration = configuration;
    }

    @Override
    public boolean supports(final Credential credential) {
        return credential != null && (WsFederationCredential.class.isAssignableFrom(credential.getClass()));
    }

}


text:
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.

Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.[Shared].TestHooks
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework
Imports Roslyn.Test.Utilities

Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim
    <[UseExportProvider]>
    Public Class AnalyzerReferenceTests
        <WpfFact>
        Public Async Function RemoveAndReAddInSameBatchWorksCorrectly() As Task
            Using environment = New TestEnvironment(GetType(TestDynamicFileInfoProviderThatProducesNoFiles))
                Dim project = Await environment.ProjectFactory.CreateAndAddToWorkspaceAsync(
                    "Project", LanguageNames.CSharp, CancellationToken.None)
                Const analyzerPath = "Z:\TestAnalyzer.dll"

                project.AddAnalyzerReference(analyzerPath)

                Using project.CreateBatchScope()
                    project.RemoveAnalyzerReference(analyzerPath)
                    project.AddAnalyzerReference(analyzerPath)
                    project.RemoveAnalyzerReference(analyzerPath)
                    project.AddAnalyzerReference(analyzerPath)
                End Using

                ' In the end, we should have exactly one reference
                Assert.Single(environment.Workspace.CurrentSolution.Projects.Single().AnalyzerReferences)
            End Using
        End Function

        <WpfTheory>
        <CombinatorialData>
        Public Async Function LoadDiagnosticsRemovedOnAnalyzerReferenceRemoval(removeInBatch As Boolean) As Task
            Using environment = New TestEnvironment(GetType(TestDynamicFileInfoProviderThatProducesNoFiles))
                Dim project = Await environment.ProjectFactory.CreateAndAddToWorkspaceAsync(
                    "Project", LanguageNames.CSharp, CancellationToken.None)
                Dim analyzerPath = "Z:\TestAnalyzer" + Guid.NewGuid().ToString() + ".dll"

                project.AddAnalyzerReference(analyzerPath)

                ' Force there to be errors trying to load the missing DLL
                Dim analyzers = environment.Workspace.CurrentSolution.Projects.Single().AnalyzerReferences.Single().GetAnalyzers(LanguageNames.CSharp)
                Assert.Empty(analyzers)

                Assert.Single(Await GetDiagnostics(environment), Function(d) d.Id = AnalyzerHelper.WRN_UnableToLoadAnalyzerIdCS)

                Using If(removeInBatch, project.CreateBatchScope(), Nothing)
                    project.RemoveAnalyzerReference(analyzerPath)
                End Using

                Assert.Empty(Await GetDiagnostics(environment))
            End Using
        End Function

        <WpfTheory>
        <CombinatorialData>
        Public Async Function LoadDiagnosticsRemovedOnProjectRemoval(removeInBatch As Boolean) As Task
            Using environment = New TestEnvironment(GetType(TestDynamicFileInfoProviderThatProducesNoFiles))
                Dim project = Await environment.ProjectFactory.CreateAndAddToWorkspaceAsync(
                    "Project", LanguageNames.CSharp, CancellationToken.None)
                Dim analyzerPath = "Z:\TestAnalyzer" + Guid.NewGuid().ToString() + ".dll"

                project.AddAnalyzerReference(analyzerPath)

                ' Force there to be errors trying to load the missing DLL
                Dim analyzers = environment.Workspace.CurrentSolution.Projects.Single().AnalyzerReferences.Single().GetAnalyzers(LanguageNames.CSharp)
                Assert.Empty(analyzers)
                Assert.Single(Await GetDiagnostics(environment), Function(d) d.Id = AnalyzerHelper.WRN_UnableToLoadAnalyzerIdCS)

                Using If(removeInBatch, project.CreateBatchScope(), Nothing)
                    project.RemoveFromWorkspace()
                End Using

                Assert.Empty(Await GetDiagnostics(environment))
            End Using
        End Function

        <WpfFact>
        Public Async Function LoadDiagnosticsStayIfRemoveAndAddInBatch() As Task
            Using environment = New TestEnvironment(GetType(TestDynamicFileInfoProviderThatProducesNoFiles))
                Dim project = Await environment.ProjectFactory.CreateAndAddToWorkspaceAsync(
                    "Project", LanguageNames.CSharp, CancellationToken.None)
                Dim analyzerPath = "Z:\TestAnalyzer" + Guid.NewGuid().ToString() + ".dll"

                project.AddAnalyzerReference(analyzerPath)

                ' Force there to be errors trying to load the missing DLL
                Dim analyzers = environment.Workspace.CurrentSolution.Projects.Single().AnalyzerReferences.Single().GetAnalyzers(LanguageNames.CSharp)
                Assert.Empty(analyzers)
                Assert.Single(Await GetDiagnostics(environment), Function(d) d.Id = AnalyzerHelper.WRN_UnableToLoadAnalyzerIdCS)

                Using project.CreateBatchScope()
                    project.RemoveAnalyzerReference(analyzerPath)
                    project.AddAnalyzerReference(analyzerPath)
                End Using

                ' We should still have a diagnostic; the real point of this assertion isn't that
                ' we keep it around immediately, but we don't accidentally screw up the batching and
                ' lose the diagnostic permanently.
                Assert.Single(Await GetDiagnostics(environment), Function(d) d.Id = AnalyzerHelper.WRN_UnableToLoadAnalyzerIdCS)
            End Using
        End Function

        Private Shared Async Function GetDiagnostics(environment As TestEnvironment) As Task(Of ImmutableArray(Of DiagnosticData))
            ' Wait for diagnostics to be updated asynchronously
            Dim waiter = environment.ExportProvider.GetExportedValue(Of AsynchronousOperationListenerProvider).GetWaiter(FeatureAttribute.DiagnosticService)
            Await waiter.ExpeditedWaitAsync()

            Dim diagnosticService = environment.ExportProvider.GetExportedValue(Of IDiagnosticService)
            Dim diagnostics = Await diagnosticService.GetDiagnosticsAsync(
                environment.Workspace,
                project:=Nothing,
                document:=Nothing,
                includeSuppressedDiagnostics:=True,
                forPullDiagnostics:=False,
                DiagnosticMode.Default,
                CancellationToken.None)
            Return diagnostics
        End Function
    End Class
End Namespace


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.salomax</groupId>
    <artifactId>machine-learning</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>1.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.2</version>
        </dependency>
        <dependency>
		    <groupId>gov.nist.math</groupId>
		    <artifactId>jama</artifactId>
		    <version>1.0.3</version>
		</dependency>
        <dependency>
            <groupId>jfree</groupId>
            <artifactId>jfreechart</artifactId>
            <version>1.0.13</version>
        </dependency>
    </dependencies>

</project>


text:
import { Injectable } from '@angular/core';

import { ItemService } from '../../items/item.service';
import { DungeonService } from '../../dungeon/dungeon.service';
import { SettingsService } from '../../settings/settings.service';
import { BossService } from '../../boss/boss.service';

import { Availability } from '../availability';
import { Dungeon } from '../../dungeon/dungeon';
import { Location } from '../../dungeon/location';
import { EntranceLock } from '../../dungeon/entrance-lock';

import { DungeonLocation } from './dungeon-location';
import { DungeonLocations } from './dungeon-location.repository';

import { Sword } from '../../items/sword';
import { Glove } from '../../items/glove';
import { Shield } from '../../items/shield';

@Injectable()
export class DungeonLocationService {
  constructor(
    private _inventory: ItemService,
    private _dungeons: DungeonService,
    private _settings: SettingsService,
    private _boss: BossService
  ) {
    this._dungeonLocations = DungeonLocations;
    this._bossAvailability = new Map<Location, () => Availability>(
      [
        [Location.CastleTower, this.canNavigateCastleTower],
        [Location.EasternPalace, this.canNavigateEasternPalace],
        [Location.DesertPalace, this.canNavigateDesertPalace],
        [Location.TowerOfHera, this.canNavigateTowerOfHera],
        [Location.PalaceOfDarkness, this.canNavigatePalaceOfDarkness],
        [Location.SwampPalace, this.canNavigateSwampPalace],
        [Location.SkullWoods, this.canNavigateSkullWoods],
        [Location.ThievesTown, this.canNavigateThievesTown],
        [Location.IcePalace, this.canNavigateIcePalace],
        [Location.MiseryMire, this.canNavigateMiseryMire],
        [Location.TurtleRock, this.canNavigateTurtleRock],
        [Location.GanonsTower, this.canNavigateGanonsTower]
      ]
    );

    this._chestAvailability = new Map<Location, () => Availability>(
      [
        [Location.CastleTower, this.canRaidCastleTower],
        [Location.EasternPalace, this.canRaidEasternPalace],
        [Location.DesertPalace, this.canRaidDesertPalace],
        [Location.TowerOfHera, this.canRaidTowerOfHera],
        [Location.PalaceOfDarkness, this.canRaidPalaceOfDarkness],
        [Location.SwampPalace, this.canRaidSwampPalace],
        [Location.SkullWoods, this.canRaidSkullWoods],
        [Location.ThievesTown, this.canRaidThievesTown],
        [Location.IcePalace, this.canRaidIcePalace],
        [Location.MiseryMire, this.canRaidMiseryMire],
        [Location.TurtleRock, this.canRaidTurtleRock],
        [Location.GanonsTower, this.canRaidGanonsTower]
      ]
    );
  }

  private _bossAvailability: Map<Location, () => Availability>;
  private _chestAvailability: Map<Location, () => Availability>;
  private _dungeonLocations: Map<Location, DungeonLocation>;

  private canEnterCastleTower(): Availability {
    const items = this._inventory;
    if ( !!items.cape ) {
      return Availability.Available;
    }

    if ( this._settings.isSwordless() ) {
      if ( !!items.hammer ) {
        return Availability.Available;
      }
    }

    if ( items.sword !== Sword.None && items.sword !== Sword.Wooden ) {
      return Availability.Available;
    }

    return Availability.Unavailable;
  }

  private canNavigateCastleTower(): Availability {
    const items = this._inventory;

    const canEnter = this.canEnterCastleTower();
    if ( canEnter !== Availability.Available ) {
      return canEnter;
    }

    const canNavigateDungeon = items.hasReliableWeapon();

    const canBeatAgahnim = this._boss.canDefeatBoss(Location.CastleTower);

    if ( !canEnter || !canNavigateDungeon || !canBeatAgahnim ) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() ) {
      const dungeon = this._dungeons.getDungeon(Location.CastleTower);
      if ( dungeon.smallKeyCount !== dungeon.maxSmallKeys ) {
        return Availability.Unavailable;
      }
    }

    return items.lantern ? Availability.Available : Availability.Glitches;
  }

  private canRaidCastleTower(): Availability {
    if ( !this._settings.isKeysanity() ) {
      return this.canNavigateCastleTower();
    }

    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.CastleTower);

    let hasMeleeWeapon: boolean;
    if ( this._settings.isSwordless() ) {
      hasMeleeWeapon = !!items.hammer;
    } else {
      hasMeleeWeapon = ( items.sword !== Sword.None && items.sword !== Sword.Wooden );
    }

    const canEnter = hasMeleeWeapon || items.cape;

    if ( !canEnter ) {
      return Availability.Unavailable;
    }

    if ( dungeon.smallKeyCount === 0 ) {
      return Availability.Possible;
    }

    return items.lantern ? Availability.Available : Availability.Glitches;
  }

  private canEnterEasternPalace(): Availability {
    return Availability.Available;
  }

  private canNavigateEasternPalace(): Availability {
    const dungeon = this._dungeons.getDungeon(Location.EasternPalace);
    if ( this._settings.isKeysanity() && !dungeon.hasBigKey ) {
      return Availability.Unavailable;
    }

    if ( !this._inventory.bow ) {
      return Availability.Unavailable;
    }

    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    return this._inventory.lantern ? Availability.Available : Availability.Glitches;
  }

  private canRaidEasternPalaceInkeysanity( dungeon: Dungeon, items: ItemService): Availability {
    if ( dungeon.hasBigKey && items.bow && items.lantern ) {
      return Availability.Available;
    }

    if ( dungeon.totalChestCount >= 4 ) {
      return Availability.Possible;
    }

    if ( dungeon.totalChestCount >= 3 && !dungeon.hasBigKey && !items.lantern ) {
      return Availability.Glitches;
    }

    if ( dungeon.totalChestCount >= 3 && ( dungeon.hasBigKey || items.lantern ) ) {
      return Availability.Possible;
    }

    if ( dungeon.totalChestCount >= 2 && dungeon.hasBigKey ) {
      return items.lantern ? Availability.Possible : Availability.Glitches;
    }

    if ( dungeon.hasBigKey && items.bow && !items.lantern ) {
      return Availability.Glitches;
    }

    return Availability.Unavailable;
  }

  private canRaidEasternPalace(): Availability {
    const dungeon = this._dungeons.getDungeon(Location.EasternPalace);
    const items = this._inventory;
    if ( this._settings.isKeysanity() ) {
      return this.canRaidEasternPalaceInkeysanity( dungeon, items );
    }

    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    if ( count <= 2 && !items.lantern ) {
      return Availability.Possible;
    }

    if ( count === 1 && !items.bow ) {
      return Availability.Possible;
    }

    return Availability.Available;
  }

  private canEnterDesertPalace(): Availability {
    const items = this._inventory;
    const canEnterLightWay = items.book;
    const canEnterDarkWay = items.hasDarkMireMirrorAccess();

    if ( !canEnterDarkWay && !canEnterLightWay ) {
      return Availability.Unavailable;
    }

    return Availability.Available;
  }

  private canNavigateDesertPalace(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.DesertPalace);
    const isKeysanity = this._settings.isKeysanity();

    const canEnter = this.canEnterDesertPalace();
    if ( canEnter !== Availability.Available ) {
      return canEnter;
    }

    if ( isKeysanity && !dungeon.hasBigKey ) {
      return Availability.Unavailable;
    }

    if (!items.hasFireSource()) {
      return Availability.Unavailable;
    }

    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( isKeysanity || items.boots ) {
      return Availability.Available;
    }

    return Availability.Possible;
  }

  private canRaidDesertPalaceInkeysanity( dungeon: Dungeon, items: ItemService ): Availability {
    const keys = dungeon.smallKeyCount;
    if ( dungeon.hasBigKey && keys === 1 && items.hasGlove() &&
      items.hasFireSource() && items.boots ) {
      return Availability.Available;
    }

    const remainingItems = dungeon.totalChestCount;
    let availableItems = 1;
    if ( !!items.boots ) {
      availableItems += 1;
    }

    if ( keys === 1 ) {
      // TODO: Ensure enemies can be defeated in this room.
      availableItems += 2;
    }

    if ( dungeon.hasBigKey ) {
      // TODO: Ensure enemies can be defeated in this far room.
      availableItems += ( ( items.hasGlove() && items.hasFireSource() ) ? 2 : 1 );
    }

    if ( dungeon.totalChestCount > dungeon.maxTotalChests - availableItems) {
      return Availability.Possible;
    }

    return Availability.Unavailable;
  }

  private canRaidDesertPalace(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.DesertPalace);

    const canEnter = this.canEnterDesertPalace();
    if ( canEnter !== Availability.Available ) {
      return canEnter;
    }

    if ( this._settings.isKeysanity() ) {
      return this.canRaidDesertPalaceInkeysanity( dungeon, items );
    }

    if ( items.hasGlove() && items.hasFireSource() && items.boots ) {
      return Availability.Available;
    }

    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    return count > 1 && items.boots ? Availability.Available : Availability.Possible;
  }

  private canEnterTowerOfHera(): Availability {
    const items = this._inventory;

    if ( !items.hasDeathMountainAccess() ) {
      return Availability.Unavailable;
    }

    if ( !items.mirror && !( !!items.hookshot && !!items.hammer ) ) {
      return Availability.Unavailable;
    }

    return items.hasDeathMountainLogicalAccess()
      ? Availability.Available
      : Availability.Glitches;
  }

  private canNavigateTowerOfHera(): Availability {
    const dungeon = this._dungeons.getDungeon(Location.TowerOfHera);
    const items = this._inventory;

    const canEnter = this.canEnterTowerOfHera();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( !this._settings.isKeysanity() ) {
      return this.canRaidTowerOfHera();
    }

    if ( !dungeon.hasBigKey ) {
      return Availability.Unavailable;
    }

    return canEnter;
  }

  private canRaidTowerOfHera(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.TowerOfHera);

    const canEnter = this.canEnterTowerOfHera();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    if ( this._settings.isKeysanity() ) {
      if ( !items.hasDeathMountainAccess()) {
        return Availability.Unavailable;
      }

      const isInLogic = canEnter === Availability.Available;
      const canGetBasement = dungeon.smallKeyCount === 1 && items.hasFireSource();

      if ( dungeon.hasBigKey && items.hasMelee() && canGetBasement) {
        return !isInLogic ? Availability.Glitches : Availability.Available;
      }

      const chests = dungeon.totalChestCount;
      const keys = dungeon.smallKeyCount;

      if ( chests >= 5) {
        return !isInLogic ? Availability.Glitches : Availability.Possible;
      }

      if ( chests >= 4 && canGetBasement) {
        return !isInLogic ? Availability.Glitches : Availability.Possible;
      }

      if ( chests >= 3 && dungeon.hasBigKey ) {
        return !isInLogic ? Availability.Glitches : Availability.Possible;
      }

      if ( chests >= 2 && dungeon.hasBigKey && ( items.hasMelee() || canGetBasement ) ) {
        return !isInLogic ? Availability.Glitches : Availability.Possible;
      }

      return Availability.Unavailable;
    }

    if ( !items.hasFireSource() ) {
      return Availability.Possible;
    }

    return canEnter;
  }

  private canEnterPalaceOfDarkness(): Availability {
    const items = this._inventory;

    // Flute location 5.
    if ( !!items.hammer && items.hasGlove() ) {
      return Availability.Available;
    }

    if ( items.glove === Glove.Titan && items.moonPearl && items.flippers ) {
      return Availability.Available;
    }

    if ( this.isCastleTowerDefeated() ) {
      return !!items.lantern ? Availability.Available : Availability.Glitches;
    }

    return Availability.Unavailable;
  }

  private canNavigatePalaceOfDarkness(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.PalaceOfDarkness);

    const canEnter = this.canEnterPalaceOfDarkness();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const needsBunnyRevival = !items.moonPearl;
    const hasNoBombs = !items.bomb;
    const hasNoLamp = !items.lantern;

    const mustSequenceBreak = needsBunnyRevival || hasNoLamp;

    if ( !items.bow || !items.hammer ) {
      return Availability.Unavailable;
    }

    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() ) {
      if ( !dungeon.hasBigKey || dungeon.smallKeyCount === 0 ) {
        return Availability.Unavailable;
      }

      if ( dungeon.smallKeyCount < 6) {
        return !mustSequenceBreak ? Availability.Possible : Availability.Glitches;
      }
    }

    return !mustSequenceBreak ? Availability.Available : Availability.Glitches;
  }

  private canRaidPalaceOfDarknessInKeysanity( dungeon: Dungeon, items: ItemService ): Availability {
    if ( dungeon.smallKeyCount === 6 && dungeon.hasBigKey && items.hammer && items.bow && items.lantern ) {
      return Availability.Available;
    }

    // TODO: Possibly change the logic since it will be tricky here.
    let currentKeys = dungeon.smallKeyCount;
    let reachableChests = 1;
    let darkChests = 0;

    if ( items.bow ) {
      // The bow is required for the right hand side.
      reachableChests += 1;
      if ( items.bomb ) {
        reachableChests += 1;
      }
    }

    if ( items.bow && items.hammer ) {
      reachableChests += 2; // The bridge and dropdown are accessible.
    } else if ( currentKeys > 0 ) {
      reachableChests += 2;
      currentKeys -= 1; // The front door had to be used.
    }

    if ( currentKeys > 0 ) {
      reachableChests += 3; // Back side of POD: the likely ones at least.
      currentKeys -= 1;
      darkChests += 2;
    }

    if ( currentKeys > 0 ) {
      // The dark area with the big chest.
      const canGetBigChest = dungeon.hasBigKey && items.bomb;
      reachableChests += canGetBigChest ? 3 : 2;
      currentKeys -= 1;
      darkChests += canGetBigChest ? 3 : 2;
    }

    if ( items.bow && items.hammer && dungeon.hasBigKey && currentKeys > 0) {
      reachableChests += 1; // King Helmasaur: prioritized in a special way.
      currentKeys -= 1;
      darkChests += 1;
    }

    if ( currentKeys > 0) {
      reachableChests += 1; // Spike Room
      currentKeys -= 1;
    }

    if ( currentKeys > 0 && items.bomb ) {
      reachableChests += 1; // The vanilla big key chest overlooking the lobby
      currentKeys -= 1;
    }

    // Moon pearl is not needed if you use bunny revival.
    if ( dungeon.totalChestCount > dungeon.maxTotalChests - reachableChests) {
      if ( dungeon.totalChestCount > dungeon.maxTotalChests - (reachableChests - darkChests)) {
        return items.moonPearl ? Availability.Possible : Availability.Glitches;
      }
      return items.lantern && items.moonPearl ? Availability.Possible : Availability.Glitches;
    }

    return Availability.Unavailable;
  }

  private canRaidPalaceOfDarkness(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon( Location.PalaceOfDarkness );

    const canEnter = this.canEnterPalaceOfDarkness();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    if ( this._settings.isKeysanity() ) {
      return this.canRaidPalaceOfDarknessInKeysanity( dungeon, items );
    }

    if ( !items.moonPearl ) {
      // Bunny revival.
      return Availability.Glitches;
    }

    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    return !(items.bow && !!items.lantern) || count === 1 && !items.hammer ?
      Availability.Possible : Availability.Available;
  }

  private canEnterSwampPalace(): Availability {
    const items = this._inventory;

    // Remember that the mirror is not required to "enter".
    // Just getting to the location is enough.

    // Defeat Agahnim, then take the direct path.
    if ( this.isCastleTowerDefeated() && !!items.moonPearl && !!items.hammer ) {
      return Availability.Available;
    }

    // Travel counter-clockwise while staying dry.
    if ( this.isCastleTowerDefeated() && !!items.moonPearl && !!items.hookshot && items.hasGlove() ) {
      return Availability.Available;
    }

    // Travel counter-clockwise while getting wet.
    if ( this.isCastleTowerDefeated() && !!items.moonPearl && !!items.hookshot && !!items.flippers ) {
      return Availability.Available;
    }

    // Start south of home.
    if ( items.hasGlove() && items.hammer ) {
      return Availability.Available;
    }

    // Start at Skull Woods area.
    if ( items.glove === Glove.Titan ) {
      return Availability.Available;
    }

    return Availability.Unavailable;
  }

  private canNavigateSwampPalace(): Availability {
    const items = this._inventory;

    const canEnter = this.canEnterSwampPalace();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    if ( !items.moonPearl || !items.mirror || !items.flippers ) {
      return Availability.Unavailable;
    }

    if ( !items.hammer || !items.hookshot ) {
      return Availability.Unavailable;
    }

    if ( !items.hasGlove() && !this.isCastleTowerDefeated() ) {
      return Availability.Unavailable;
    }

    const dungeon = this._dungeons.getDungeon(Location.SwampPalace);

    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() && dungeon.smallKeyCount === 0 ) {
      return Availability.Unavailable;
    }

    return Availability.Available;
  }

  private canRaidSwampPalaceInKeysanity( dungeon: Dungeon, items: ItemService ): Availability {
    if ( dungeon.hasBigKey && dungeon.smallKeyCount === 1 && items.hammer && items.hookshot ) {
      return Availability.Available;
    }

    const chests = dungeon.totalChestCount;
    const keys = dungeon.smallKeyCount;

    if ( chests === 10 ) {
      return Availability.Possible;
    }

    if ( chests >= 9 && keys === 1 ) {
      return Availability.Possible;
    }

    if ( chests >= 6 && keys === 1 && items.hammer ) {
      return Availability.Possible;
    }

    if ( chests >= 5 && dungeon.hasBigKey && keys === 1 && items.hammer ) {
      return Availability.Possible;
    }

    if ( chests >= 2 && keys === 1 && items.hammer && items.hookshot ) {
      return Availability.Possible;
    }

    return Availability.Unavailable;
  }

  private canRaidSwampPalace(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.SwampPalace);

    const canEnter = this.canEnterSwampPalace();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    if ( !items.moonPearl || !items.mirror || !items.flippers ) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() ) {
      return this.canRaidSwampPalaceInKeysanity( dungeon, items );
    }

    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    if ( count <= 2) {
      return !items.hammer || !items.hookshot ? Availability.Unavailable : Availability.Available;
    }

    if ( count <= 4) {
      return !items.hammer ? Availability.Unavailable : !items.hookshot ? Availability.Possible : Availability.Available;
    }

    if ( count <= 5) {
      return !items.hammer ? Availability.Unavailable : Availability.Available;
    }

    return !items.hammer ? Availability.Possible : Availability.Available;
  }

  private canEnterSkullWoods(): Availability {
    const items = this._inventory;

    // Defeat Agahnim, then travel counter-clockwise while staying dry.
    if ( this.isCastleTowerDefeated() && !!items.moonPearl && items.hasGlove() && !!items.hookshot ) {
      return Availability.Available;
    }

    // Defeat Agahnim, then travel counter-clockwise while getting wet.
    if ( this.isCastleTowerDefeated() && !!items.moonPearl && !!items.flippers && !!items.hookshot ) {
      return Availability.Available;
    }

    // Use the Skull Woods warp.
    if ( items.hasGlove() && items.hammer ) {
      return Availability.Available;
    }

    // Use the Skull Woods warp.
    if ( items.glove === Glove.Titan ) {
      return Availability.Available;
    }

    return Availability.Unavailable;
  }

  private canNavigateSkullWoods(): Availability {
    const items = this._inventory;

    const canEnter = this.canEnterSkullWoods();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canAvoidBunnyRevival = items.moonPearl;

    if ( !items.fireRod ) {
      return Availability.Unavailable;
    }

    const dungeon = this._dungeons.getDungeon(Location.SkullWoods);
    if (!this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( !this._settings.isSwordless() && items.sword === Sword.None ) {
      return Availability.Unavailable;
    }

    return canAvoidBunnyRevival ? Availability.Available : Availability.Glitches;
  }

  private canRaidSkullWoods(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.SkullWoods);
    const canEnter = this.canEnterSkullWoods();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canAvoidBunnyRevival = !!items.moonPearl;

    if ( this._settings.isKeysanity() ) {
      const chests = dungeon.totalChestCount;
      const canGoBeyondCurtain = this._settings.isSwordless() || items.hasSword();

      if ( dungeon.hasBigKey && items.fireRod && canGoBeyondCurtain ) {
        return canAvoidBunnyRevival ? Availability.Available : Availability.Glitches;
      }

      if ( chests >= 4 ) {
        return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
      }

      if ( chests >= 3 && (dungeon.hasBigKey || items.fireRod )) {
        return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
      }

      if ( chests >= 2 && items.fireRod && ( canGoBeyondCurtain || dungeon.hasBigKey ) ) {
        return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
      }

      return Availability.Unavailable;
    }

    const tmp = items.fireRod ? Availability.Available : Availability.Possible;
    return canAvoidBunnyRevival ? tmp : Availability.Glitches;
  }

  private canEnterThievesTown(): Availability {
    return this.canEnterSkullWoods();
  }

  private canNavigateThievesTown(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.ThievesTown);

    const canEnter = this.canEnterSkullWoods();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    // The roof must be blown open.
    if ( !items.bomb && !this._settings.isBossShuffleOn() ) {
      return Availability.Unavailable;
    }

    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() && !dungeon.hasBigKey) {
      return Availability.Unavailable;
    }

    return !!items.moonPearl ? Availability.Available : Availability.Glitches;
  }

  private canRaidThievesTown(): Availability {
    const dungeon = this._dungeons.getDungeon(Location.ThievesTown);
    const items = this._inventory;
    const canEnter = this.canEnterSkullWoods();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canAvoidBunnyRevival = !!items.moonPearl;

    if ( this._settings.isKeysanity()) {
      const chests = dungeon.totalChestCount;
      const keys = dungeon.smallKeyCount;
      if ( dungeon.hasBigKey && keys === 1 && items.hammer ) {
        return canAvoidBunnyRevival ? Availability.Available : Availability.Glitches;
      }

      if ( chests >= 5) {
        return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
      }

      if ( chests >= 3 && dungeon.hasBigKey) {
        return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
      }

      if ( chests >= 2 && dungeon.hasBigKey && ( items.hasMelee() || items.hasCane() ) ) {
        return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
      }

      return Availability.Unavailable;
    }

    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    const tmp = count === 1 && !items.hammer ?
      Availability.Possible : Availability.Available;

    return canAvoidBunnyRevival ? tmp : Availability.Glitches;
  }

  private canEnterIcePalace(): Availability {
    const items = this._inventory;
    if ( items.glove !== Glove.Titan ) {
      return Availability.Unavailable;
    }

    return !!items.flippers ? Availability.Available : Availability.Glitches;
  }

  private canNavigateIcePalace(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.IcePalace);

    const canEnter = this.canEnterIcePalace();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canAvoidBunnyRevival = !!items.moonPearl;

    if ( !items.hammer ) {
      return Availability.Unavailable;
    }

    if ( !this._boss.canDefeatBoss(dungeon.bossId) ) {
      return Availability.Unavailable;
    }

    let tmp: Availability;

    if ( this._settings.isKeysanity() ) {
      const keys = dungeon.smallKeyCount;
      const hasRightKeys = keys > 0 && !!items.somaria || keys > 1;
      tmp = hasRightKeys ? Availability.Available : Availability.Possible;
      return canAvoidBunnyRevival && canEnter === Availability.Available
        ? tmp
        : Availability.Glitches;
    }

    tmp = items.hookshot || items.somaria ? Availability.Available : Availability.Glitches;
    return canAvoidBunnyRevival && canEnter === Availability.Available
      ? tmp
      : Availability.Glitches;
  }

  private canRaidIcePalace(): Availability {
    const items = this._inventory;
    const canEnter = this.canEnterIcePalace();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canAvoidBunnyRevival = !!items.moonPearl;

    if ( !items.fireRod && !(items.bombos && items.hasMelee())) {
      return Availability.Unavailable;
    }

    if ( !this._settings.isKeysanity()) {
      return !!items.hammer && canAvoidBunnyRevival ? Availability.Available : Availability.Glitches;
    }

    const dungeon = this._dungeons.getDungeon(Location.IcePalace);
    const keys = dungeon.smallKeyCount;
    const chests = dungeon.totalChestCount;

    if ( dungeon.hasBigKey && items.hammer ) {
      const tmp = ( keys > 0 && items.somaria || keys > 1 ) ? Availability.Available : Availability.Possible;
      return canAvoidBunnyRevival ? tmp : Availability.Glitches;
    }

    if ( chests >= 5 ) {
      return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
    }

    if ( chests >= 4 && dungeon.hasBigKey ) {
      return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
    }

    if ( chests >= 2 && items.hammer ) {
      return canAvoidBunnyRevival ? Availability.Possible : Availability.Glitches;
    }

    return Availability.Unavailable;
  }

  private canEnterMiseryMire(): Availability {
    const items = this._inventory;

    // We must flute to 6.
    if ( !items.flute ) {
      return Availability.Unavailable;
    }

    // We must be able to lift the rock.
    if ( items.glove !== Glove.Titan ) {
      return Availability.Unavailable;
    }

    // We must have the moon pearl to use the medallion.
    if ( !items.moonPearl ) {
      return Availability.Unavailable;
    }

    // We must have the right weapon and the right medallion.
    const medallionState = this.medallionState( Location.MiseryMire );
    return medallionState;
  }

  private canNavigateMiseryMire(): Availability {
    const items = this._inventory;

    const canEnter = this.canEnterMiseryMire();

    if ( !items.somaria ) {
      return Availability.Unavailable;
    }

    if (!items.boots && !items.hookshot) {
      return Availability.Unavailable;
    }

    const medallionState = this.canEnterMiseryMire();
    if ( medallionState !== Availability.Available ) {
      return medallionState;
    }

    const dungeon = this._dungeons.getDungeon(Location.MiseryMire);
    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() ) {
      if ( !dungeon.hasBigKey) {
        return Availability.Unavailable;
      }

      return items.lantern ? Availability.Available : Availability.Glitches;
    }

    if ( !items.hasFireSource() ) {
      return Availability.Possible;
    }

    return items.lantern ? Availability.Available : Availability.Glitches;
  }

  private canRaidMiseryMireInKeysanity( dungeon: Dungeon, items: ItemService ): Availability {
    const chests = dungeon.totalChestCount;
    if ( items.lantern && items.somaria && dungeon.hasBigKey ) {
      return Availability.Available;
    }

    if ( chests >= 5) {
      return Availability.Possible;
    }

    const hasFire = items.hasFireSource();

    if ( chests >= 3 ) {
      if ( dungeon.hasBigKey || hasFire) {
        return Availability.Possible;
      }

      if ( dungeon.hasBigKey && items.somaria && !hasFire) {
        return Availability.Glitches;
      }
    }

    if ( chests >= 2 && items.fireRod && dungeon.hasBigKey) {
      return Availability.Possible;
    }

    if ( chests >= 1 && items.fireRod && !items.lantern && items.somaria && dungeon.hasBigKey) {
      return Availability.Glitches;
    }

    return Availability.Unavailable;
  }

  private canRaidMiseryMire(): Availability {
    const items = this._inventory;
    const dungeon = this._dungeons.getDungeon(Location.MiseryMire);

    if (!items.boots && !items.hookshot) {
      return Availability.Unavailable;
    }

    const medallionState = this.canEnterMiseryMire();
    if ( medallionState !== Availability.Available ) {
      return medallionState;
    }

    if ( this._settings.isKeysanity()) {
      return this.canRaidMiseryMireInKeysanity( dungeon, items );
    }

    let hasItems: boolean;
    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    if ( count > 1 ) {
      hasItems = items.hasFireSource();
    } else {
      hasItems = !!items.lantern && !!items.somaria && !!items.bomb;
    }

    return hasItems ? Availability.Available : Availability.Possible;
  }

  private canEnterTurtleRock(): Availability {
    const items = this._inventory;

    // We must have the moon pearl to use the medallion.
    if ( !items.moonPearl ) {
      return Availability.Unavailable;
    }

    // We must hammer the pegs to open the warp.
    if ( !items.hammer ) {
      return Availability.Unavailable;
    }

    // We must be able to lift the rock.
    if ( items.glove !== Glove.Titan ) {
      return Availability.Unavailable;
    }

    // We need either the mirror or hookshot for traversal.
    if ( !items.mirror && !items.hookshot ) {
      return Availability.Unavailable;
    }

    // We must have the right weapon and the right medallion.
    const medallionState = this.medallionState( Location.TurtleRock );

    if ( medallionState === Availability.Unavailable ) {
      return medallionState;
    }

    // Either the lamp or flute is required for logical purposes.
    if ( !!items.lantern || !!items.flute ) {
      return medallionState;
    }

    return Availability.Glitches;
  }

  private canNavigateTurtleRock(): Availability {
    const items = this._inventory;

    const canEnter = this.canEnterTurtleRock();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canEnterCleanly = canEnter !== Availability.Glitches;

    // The cane of somaria is needed just for the purposes of
    if ( !items.somaria ) {
      return Availability.Unavailable;
    }

    // In non entrance modes, a bomb is needed for one wall.
    if ( !items.bomb ) {
      return Availability.Unavailable;
    }

    // Both rods are required for the boss.
    if ( !items.iceRod || !items.fireRod ) {
      return Availability.Unavailable;
    }

    const dungeon = this._dungeons.getDungeon(Location.TurtleRock);
    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() ) {
      if ( !dungeon.hasBigKey || dungeon.smallKeyCount < 3) {
        return Availability.Unavailable;
      }

      if ( dungeon.smallKeyCount === 3) {
        return items.lantern && canEnterCleanly ? Availability.Possible : Availability.Glitches;
      }

      return items.lantern && canEnterCleanly ? Availability.Available : Availability.Glitches;
    }

    if ( !this.hasLaserBridgeSafety()) {
      return Availability.Possible;
    }

    return items.lantern && canEnterCleanly ? Availability.Available : Availability.Glitches;
  }

  private canRaidTurtleRockInKeysanity( dungeon: Dungeon, items: ItemService ): Availability {
    const chests = dungeon.totalChestCount;
    const keys = dungeon.smallKeyCount;
    const hasLaserSafety = this.hasLaserBridgeSafety();

    if ( dungeon.hasBigKey && keys === 4 && items.fireRod && items.iceRod && items.lantern && hasLaserSafety ) {
      return Availability.Available;
    }

    if ( chests >= 12) {
      return Availability.Possible;
    }

    if ( chests >= 10 && ( items.fireRod || keys >= 2 ) ) {
      return Availability.Possible;
    }

    if ( chests >= 9 && ( ( keys >= 1 && items.fireRod ) || ( keys >= 2 && dungeon.hasBigKey ) ) ) {
      return Availability.Possible;
    }

    if ( chests >= 8 && keys >= 2 && items.fireRod ) {
      return Availability.Possible;
    }

    if ( chests >= 7 && dungeon.hasBigKey && keys >= 2 && items.fireRod ) {
      return Availability.Possible;
    }

    if ( chests >= 5 && dungeon.hasBigKey && keys >= 2 && hasLaserSafety ) {
      return items.lantern ? Availability.Possible : Availability.Glitches;
    }

    if ( chests >= 4 && dungeon.hasBigKey && keys >= 3 && hasLaserSafety ) {
      return items.lantern ? Availability.Possible : Availability.Glitches;
    }

    if ( chests >= 3 && dungeon.hasBigKey) {
      if ( keys >= 2 && items.fireRod && hasLaserSafety ) {
        return items.lantern ? Availability.Possible : Availability.Glitches;
      }

      if ( keys === 4 && items.fireRod && items.iceRod) {
        return items.lantern ? Availability.Possible : Availability.Glitches;
      }
    }

    if ( chests >= 2 && dungeon.hasBigKey && keys >= 3 && items.fireRod && hasLaserSafety ) {
      return items.lantern ? Availability.Possible : Availability.Glitches;
    }

    return Availability.Unavailable;
  }

  private canRaidTurtleRock(): Availability {
    const items = this._inventory;

    const canEnter = this.canEnterTurtleRock();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const canEnterCleanly = canEnter !== Availability.Glitches;

    if ( !items.somaria ) {
      return Availability.Unavailable;
    }

    const dungeon = this._dungeons.getDungeon(Location.TurtleRock);
    const hasLaserSafety = this.hasLaserBridgeSafety();

    if ( this._settings.isKeysanity() ) {
      return this.canRaidTurtleRockInKeysanity( dungeon, items );
    }

    const darkAvailability = items.lantern ? Availability.Available : Availability.Glitches;

    const count = this._settings.isRetro()
      ? dungeon.retroChestCount
      : dungeon.itemChestCount;

    if ( count <= 1) {
      return !hasLaserSafety ? Availability.Unavailable : items.fireRod && items.iceRod ? darkAvailability : Availability.Possible;
    }
    if ( count <= 2) {
      return !hasLaserSafety ? Availability.Unavailable : items.fireRod ? darkAvailability : Availability.Possible;
    }

    if ( count <= 4) {
      return hasLaserSafety && items.fireRod && items.lantern ? Availability.Available : Availability.Possible;
    }

    return items.fireRod && items.lantern ? Availability.Available : Availability.Possible;
  }

  private canEnterGanonsTower(): Availability {
    const dungeons = this.getCorrectDungeons();
    if ( !this.isDungeonCountCorrect( dungeons ) ) {
      return Availability.Unavailable;
    }

    if ( !this.arePriorBossesDefeated()) {
      return Availability.Unavailable;
    }

    const items = this._inventory;

    if ( items.glove !== Glove.Titan ) {
      return Availability.Unavailable;
    }

    if ( !items.moonPearl ) {
      return Availability.Unavailable;
    }

    const canClimbSuperBunnyCave = items.hookshot;
    const canAccessTurtleRock = items.hammer;

    if ( !canClimbSuperBunnyCave && !canAccessTurtleRock ) {
      return Availability.Unavailable;
    }

    return items.hasDeathMountainLogicalAccess()
      ? Availability.Available
      : Availability.Glitches;
  }

  private canNavigateGanonsTower(): Availability {
    const items = this._inventory;
    const canEnter = this.canEnterGanonsTower();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    if ( !items.bow ) {
      return Availability.Unavailable;
    }

    if ( !items.hasFireSource() ) {
      return Availability.Unavailable;
    }

    const dungeon = this._dungeons.getDungeon(Location.GanonsTower);
    if ( !this._boss.canDefeatBoss(dungeon.bossId)) {
      return Availability.Unavailable;
    }

    if ( this._settings.isKeysanity() ) {
      if ( !dungeon.hasBigKey) {
        return Availability.Unavailable;
      }

      if ( dungeon.smallKeyCount < 3) {
        return Availability.Possible;
      }
    }

    // Not going through all of them right now.
    return canEnter;
  }

  private canRaidGanonsTower(): Availability {
    if ( !this._settings.isKeysanity() ) {
      return this.canNavigateGanonsTower();
    }

    const items = this._inventory;
    const canEnter = this.canEnterGanonsTower();
    if ( canEnter === Availability.Unavailable ) {
      return canEnter;
    }

    const dungeon = this._dungeons.getDungeon(Location.GanonsTower);
    const chests = dungeon.totalChestCount;
    const keys = dungeon.smallKeyCount;
    const hasFireSource = items.hasFireSource();

    if ( dungeon.hasBigKey && keys > 2 && items.bow && items.hookshot && hasFireSource && items.somaria) {
      return Availability.Available;
    }

    // Start counting keys and chests.
    let currentKeys = keys + 1; // free key on the left side.
    let reachableChests = 2; // two chests on the right are free.

    if ( items.boots ) {
      reachableChests += 1; // The torch.
    }

    if ( items.somaria ) {
      reachableChests += 1; // Tile Room.
    }

    if ( items.hookshot && items.hammer ) {
      reachableChests += 4; // Skeleton room, west side.
    }

    if ( dungeon.hasBigKey && items.bow && hasFireSource ) {
      reachableChests += 2;
      currentKeys += 1; // The mini helmasaur room.
    }

    // Now for some easy chests with few keys needed.
    if ( items.somaria && items.fireRod && currentKeys > 0) {
      reachableChests += 4; // End of right side. Free key in the room beyond.
    }

    if ( items.hookshot && items.hammer ) {
      reachableChests += 1; // Firebar Room. A key is used, but a freebie one is found on left side.
    }

    if ( dungeon.hasBigKey && items.bow && hasFireSource && currentKeys > 0 ) {
      reachableChests += 1;
      currentKeys -= 1; // Consolation chest.
    }

    // Now for chests that need a key to be spent.
    if ( currentKeys > 0) {
      if ( items.hookshot && items.hammer ) {
        // Rando room + Armos Knights area.
        reachableChests += dungeon.hasBigKey ? 9 : 8;
        currentKeys -= 1;
      } else if ( items.somaria && items.fireRod ) {
        // Just Armos Knights.
        reachableChests += dungeon.hasBigKey ? 5 : 4;
        currentKeys -= 1;
      }
    }

    if ( ( items.hookshot || items.bombos ) && items.hammer && currentKeys > 0 ) {
      reachableChests += 1;
      currentKeys -= 1; // Map room with double fire bars.
    }

    if ( chests > (dungeon.maxTotalChests - reachableChests ) ) {
      return Availability.Possible;
    }

    return Availability.Unavailable;
  }

  private getCorrectDungeons(): Dungeon[] {
    if ( this._settings.isGoalAllDungeons() ) {
      return this._dungeons.allDungeons();
    }

    if ( this._settings.isGoalPedestal() ) {
      return this._dungeons.pendantDungeons();
    }

    return this._dungeons.crystalDungeons();
  }

  private isDungeonCountCorrect( dungeons: Dungeon[] ): boolean {
    if ( this._settings.isGoalAllDungeons() ) {
      return true;
    }

    if ( this._settings.isGoalPedestal() ) {
      return dungeons.length >= 3;
    }

    return dungeons.length >= 7;
  }

  private arePriorBossesDefeated(): boolean {
    // Order doesn't matter. Just make sure the crystal ones are covered.
    return this._dungeons.crystalDungeons().every( e => e.isBossDefeated );
  }

  private hasLaserBridgeSafety(): boolean {
    return !!this._inventory.byrna || !!this._inventory.cape || this._inventory.shield === Shield.Mirror;
  }

  private medallionState( location: Location ): Availability {
    const dungeon = this._dungeons.getDungeon( location );
    if ( dungeon.entranceLock === EntranceLock.None) {
      return Availability.Available;
    }

    const inventory = this._inventory;

    if ( !inventory.bombos && !inventory.ether && !inventory.quake ) {
      return Availability.Unavailable;
    }

    if ( !inventory.hasPrimaryMelee() ) {
      return Availability.Unavailable;
    }

    if ( dungeon.entranceLock === EntranceLock.Bombos && !inventory.bombos ) {
      return Availability.Unavailable;
    }

    if ( dungeon.entranceLock === EntranceLock.Ether && !inventory.ether ) {
      return Availability.Unavailable;
    }

    if ( dungeon.entranceLock === EntranceLock.Quake && !inventory.quake ) {
      return Availability.Unavailable;
    }

    if ( dungeon.entranceLock === EntranceLock.Unknown && !(inventory.bombos && inventory.ether && inventory.quake)) {
      return Availability.Possible;
    }

    return Availability.Available;
  }

  private isCastleTowerDefeated(): boolean {
    return this._dungeons.getDungeon(Location.CastleTower).isBossDefeated;
  }

  getBossAvailability(id: Location): Availability {
    return this._bossAvailability.get(id).call(this);
  }

  getChestAvailability(id: Location): Availability {
    return this._chestAvailability.get(id).call(this);
  }

  getDungeonLocation(id: Location): DungeonLocation {
    return this._dungeonLocations.get(id);
  }

  getBossName(id: Location): string {
    const geographicDungeon = this._dungeons.getDungeon(id);
    const bossId = geographicDungeon.bossId;
    if ( bossId === id ) {
      return geographicDungeon.bossName;
    }

    const bossDungeon = this._dungeons.getDungeon(bossId);
    return bossDungeon.bossName;
  }

  hasChestsOrBossClaimed(id: Location): boolean {
    const dungeon = this._dungeons.getDungeon(id);

    if ( this._settings.isKeysanity() ) {
      return dungeon.totalChestCount === 0;
    }

    if ( dungeon.hasDungeonEndingReward ) {
      const count = this._settings.isRetro()
        ? dungeon.retroChestCount
        : dungeon.itemChestCount;
      return count === 0;
    }

    return dungeon.isBossDefeated;
  }

  isBossDefeated(id: Location): boolean {
    return this._dungeons.getDungeon(id).isBossDefeated;
  }

  reset(): void {
    this._dungeonLocations.forEach( l => {
    } );
  }
}