├── .gitignore ├── LICENSE.txt ├── README ├── ephemeris ├── 1900-1949.txt ├── 1950-1999.txt ├── 2001-2049.txt └── 2050-2100.txt ├── lib ├── .gitignore ├── gson-2.1.jar └── junit-4.10.jar ├── src ├── META-INF │ └── jdoconfig.xml ├── astrochart │ ├── AstroChart.gwt.xml │ ├── client │ │ ├── AppController.java │ │ ├── AstroChart.java │ │ ├── event │ │ │ ├── CancelledEvent.java │ │ │ ├── CancelledEventHandler.java │ │ │ ├── DateUpdatedEvent.java │ │ │ ├── DateUpdatedEventHandler.java │ │ │ ├── ResetAspectsEvent.java │ │ │ ├── ResetAspectsEventHandler.java │ │ │ ├── SetStatusEvent.java │ │ │ └── SetStatusEventHandler.java │ │ ├── presenter │ │ │ ├── AbstractTabPresenter.java │ │ │ ├── AdminPresenter.java │ │ │ ├── ChartPresenter.java │ │ │ ├── InfoPresenter.java │ │ │ └── Presenter.java │ │ ├── service │ │ │ ├── AdminService.java │ │ │ ├── AdminServiceAsync.java │ │ │ ├── EpochService.java │ │ │ ├── EpochServiceAsync.java │ │ │ ├── GeocodeService.java │ │ │ └── GeocodeServiceAsync.java │ │ ├── util │ │ │ ├── AstrologyUtil.java │ │ │ ├── Constants.java │ │ │ └── DateTimeUtil.java │ │ ├── view │ │ │ ├── AdminView.java │ │ │ ├── ChartView.java │ │ │ └── InfoView.java │ │ └── widgets │ │ │ ├── Chart.java │ │ │ └── TimeEntry.java │ ├── server │ │ └── service │ │ │ ├── AdminServiceImpl.java │ │ │ ├── EpochServiceImpl.java │ │ │ └── GeocodeServiceImpl.java │ └── shared │ │ ├── EquinocticalShaddowLengths.java │ │ ├── data │ │ ├── Epoch.java │ │ └── GeocodeData.java │ │ ├── enums │ │ ├── AspectType.java │ │ ├── ChartColor.java │ │ ├── ChartProportions.java │ │ ├── HouseType.java │ │ ├── Planet.java │ │ ├── RashimanaGroup.java │ │ ├── Weekday.java │ │ ├── ZodiacSign.java │ │ └── time │ │ │ ├── Month.java │ │ │ └── TimeZone.java │ │ ├── exceptions │ │ └── EpochNotFoundException.java │ │ └── wrappers │ │ ├── AscendentAndOffset.java │ │ ├── BodyPosition.java │ │ ├── RiseAndSet.java │ │ └── TextPosition.java └── log4j.properties ├── test └── astrochart │ └── client │ ├── AstroChartTestSuite.java │ ├── AstrologyUtilTester.java │ └── DateTimeUtilTester.java └── war ├── AstroChart.css ├── AstroChart.html ├── WEB-INF ├── .gitignore ├── appengine-web.xml ├── lib │ └── .gitignore ├── logging.properties └── web.xml ├── favicon.ico └── images └── AstroChartTitle.png /.gitignore: -------------------------------------------------------------------------------- 1 | /.git 2 | /.gwt 3 | 4 | /.settings 5 | 6 | /gwt-unitCache 7 | 8 | /www-test 9 | 10 | /test-classes 11 | /.project 12 | 13 | /.classpath 14 | /.checkstyle 15 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013-2017 Lukas Steiger 2 | 3 | This program is free software. It comes without any warranty, to 4 | the extent permitted by applicable law. You can redistribute it 5 | and/or modify it under the terms of the Do What The Fuck You Want 6 | To Public License, Version 2, as published by Sam Hocevar. 7 | See http://www.wtfpl.net/ for more details. 8 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Welcome to Astrology Chart Generator. 2 | http://astro-chart.appspot.com 3 | 4 | This application is work in progress and may therefore still display incorrect results. 5 | 6 | The ephemeris used in this application can be found at: 7 | http://www.findyourfate.com/astrology/ephemeris/ephemeris.html 8 | 9 | Astrology Chart Generator uses the following IP-location lookup service: 10 | http://freegeoip.net 11 | 12 | The location lookup by city-name is powered by: 13 | http://code.google.com/apis/maps/index.html 14 | 15 | Sunrise and sunset calculations are done according to the formulas provided at: 16 | http://users.electromagnetic.net/bu/astro/sunrise-set.php 17 | This application will therefore calculate the same results for sunrise and sunset as calculated here: 18 | http://users.electromagnetic.net/bu/astro/iyf-calc.php 19 | (Beware: There are many other online calculators that result in different results.) -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | /gson-2.1.jar 2 | /junit-4.10.jar 3 | -------------------------------------------------------------------------------- /lib/gson-2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tok/AstroChart/c7f7702325e46f2207c1b06f83e4d1ddc418f971/lib/gson-2.1.jar -------------------------------------------------------------------------------- /lib/junit-4.10.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tok/AstroChart/c7f7702325e46f2207c1b06f83e4d1ddc418f971/lib/junit-4.10.jar -------------------------------------------------------------------------------- /src/META-INF/jdoconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/astrochart/AstroChart.gwt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/astrochart/client/AppController.java: -------------------------------------------------------------------------------- 1 | package astrochart.client; 2 | 3 | import java.util.Date; 4 | import astrochart.client.event.CancelledEvent; 5 | import astrochart.client.event.CancelledEventHandler; 6 | import astrochart.client.presenter.AdminPresenter; 7 | import astrochart.client.presenter.InfoPresenter; 8 | import astrochart.client.presenter.ChartPresenter; 9 | import astrochart.client.presenter.Presenter; 10 | import astrochart.client.util.DateTimeUtil; 11 | import astrochart.client.view.AdminView; 12 | import astrochart.client.view.InfoView; 13 | import astrochart.client.view.ChartView; 14 | import com.google.gwt.event.logical.shared.SelectionEvent; 15 | import com.google.gwt.event.logical.shared.SelectionHandler; 16 | import com.google.gwt.event.logical.shared.ValueChangeEvent; 17 | import com.google.gwt.event.logical.shared.ValueChangeHandler; 18 | import com.google.gwt.event.shared.HandlerManager; 19 | import com.google.gwt.user.client.History; 20 | import com.google.gwt.user.client.ui.HasWidgets; 21 | import com.google.gwt.user.client.ui.TabPanel; 22 | 23 | public class AppController implements Presenter, ValueChangeHandler { 24 | private final HandlerManager eventBus = new HandlerManager(null); 25 | private final DateTimeUtil dateTimeUtil = new DateTimeUtil(); 26 | private HasWidgets container; 27 | 28 | private final TabPanel tabPanel = new TabPanel(); 29 | private final ChartView chartView = new ChartView(eventBus, dateTimeUtil); 30 | private final InfoView infoView = new InfoView(); 31 | private final AdminView adminView = new AdminView(); 32 | 33 | private ChartPresenter mainPresenter; 34 | private Presenter infoPresenter; 35 | private Presenter adminPresenter; 36 | 37 | public AppController() { 38 | prepareTabs(); 39 | bind(); 40 | } 41 | 42 | private void prepareTabs() { 43 | tabPanel.addSelectionHandler(new SelectionHandler() { 44 | @Override 45 | public void onSelection(final SelectionEvent event) { 46 | final int selection = event.getSelectedItem().intValue(); 47 | if (selection == 0) { 48 | if (!History.getToken().startsWith("chart")) { 49 | History.newItem("chart/"); 50 | } 51 | } 52 | if (selection == 1) { 53 | if (!History.getToken().startsWith("info")) { 54 | History.newItem("info/"); 55 | } 56 | } 57 | } 58 | }); 59 | //tabPanel.setAnimationEnabled(true); 60 | tabPanel.add(chartView.asWidget(), "Chart"); 61 | tabPanel.add(infoView.asWidget(), "Info"); 62 | } 63 | 64 | private void bind() { 65 | History.addValueChangeHandler(this); 66 | eventBus.addHandler(CancelledEvent.TYPE, new CancelledEventHandler() { 67 | @Override 68 | public void onCancelled(final CancelledEvent event) { 69 | doEditTermCancelled(); 70 | } 71 | }); 72 | } 73 | 74 | private void doEditTermCancelled() { 75 | History.newItem("chart/"); 76 | } 77 | 78 | @Override 79 | public final void go(final HasWidgets container) { 80 | this.container = container; 81 | if ("".equals(History.getToken())) { 82 | History.newItem("chart/"); 83 | } else { 84 | History.fireCurrentHistoryState(); 85 | } 86 | } 87 | 88 | @Override 89 | public final void onValueChange(final ValueChangeEvent event) { 90 | final String token = event.getValue(); 91 | if (token.startsWith("chart/")) { 92 | Date providedUtcDate = null; 93 | String dateString = ""; 94 | if (token.split("/").length > 1) { 95 | dateString = token.split("/")[1]; 96 | try { 97 | providedUtcDate = dateTimeUtil.getUtcDateFromUtcString(dateString); 98 | } catch (final IllegalArgumentException iae) { 99 | assert true; // ignore 100 | } 101 | } 102 | tabPanel.selectTab(0); 103 | mainPresenter = new ChartPresenter(eventBus, dateTimeUtil, tabPanel, chartView, providedUtcDate); 104 | mainPresenter.go(container); 105 | } else if (token.startsWith("info/")) { 106 | tabPanel.selectTab(1); 107 | infoPresenter = new InfoPresenter(eventBus, tabPanel, infoView); 108 | infoPresenter.go(container); 109 | } else if (token.startsWith("admin/")) { 110 | adminPresenter = new AdminPresenter(adminView); 111 | adminPresenter.go(container); 112 | } else { 113 | assert true; // ignore 114 | } 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/astrochart/client/AstroChart.java: -------------------------------------------------------------------------------- 1 | package astrochart.client; 2 | 3 | import com.google.gwt.core.client.EntryPoint; 4 | import com.google.gwt.user.client.ui.Image; 5 | import com.google.gwt.user.client.ui.RootPanel; 6 | 7 | /** 8 | * Entry point classes define onModuleLoad(). 9 | */ 10 | public class AstroChart implements EntryPoint { 11 | private final AppController appController = new AppController(); 12 | 13 | @Override 14 | public final void onModuleLoad() { 15 | final Image titleImage = new Image("/images/AstroChartTitle.png"); 16 | RootPanel.get("title").add(titleImage); 17 | appController.go(RootPanel.get("content")); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/astrochart/client/event/CancelledEvent.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.GwtEvent; 4 | 5 | public class CancelledEvent extends GwtEvent { 6 | public static final Type TYPE = new Type(); 7 | 8 | @Override 9 | public final Type getAssociatedType() { 10 | return TYPE; 11 | } 12 | 13 | @Override 14 | protected final void dispatch(final CancelledEventHandler handler) { 15 | handler.onCancelled(this); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/astrochart/client/event/CancelledEventHandler.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.EventHandler; 4 | 5 | public interface CancelledEventHandler extends EventHandler { 6 | void onCancelled(final CancelledEvent event); 7 | } 8 | -------------------------------------------------------------------------------- /src/astrochart/client/event/DateUpdatedEvent.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import java.util.Date; 4 | import com.google.gwt.event.shared.GwtEvent; 5 | 6 | public class DateUpdatedEvent extends GwtEvent { 7 | public static final Type TYPE = new Type(); 8 | private final Date localDate; 9 | 10 | public DateUpdatedEvent(final Date localDate) { 11 | this.localDate = localDate; 12 | } 13 | 14 | @Override 15 | public final Type getAssociatedType() { 16 | return TYPE; 17 | } 18 | 19 | @Override 20 | protected final void dispatch(final DateUpdatedEventHandler handler) { 21 | handler.onDateUpdated(this); 22 | } 23 | 24 | public final Date getLocalDate() { 25 | return localDate; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/astrochart/client/event/DateUpdatedEventHandler.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.EventHandler; 4 | 5 | public interface DateUpdatedEventHandler extends EventHandler { 6 | void onDateUpdated(final DateUpdatedEvent event); 7 | } 8 | -------------------------------------------------------------------------------- /src/astrochart/client/event/ResetAspectsEvent.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.GwtEvent; 4 | 5 | public class ResetAspectsEvent extends GwtEvent { 6 | public static final Type TYPE = new Type(); 7 | 8 | @Override 9 | public final Type getAssociatedType() { 10 | return TYPE; 11 | } 12 | 13 | @Override 14 | protected final void dispatch(final ResetAspectsEventHandler handler) { 15 | handler.onResetAspects(this); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/astrochart/client/event/ResetAspectsEventHandler.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.EventHandler; 4 | 5 | public interface ResetAspectsEventHandler extends EventHandler { 6 | void onResetAspects(final ResetAspectsEvent event); 7 | } 8 | -------------------------------------------------------------------------------- /src/astrochart/client/event/SetStatusEvent.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.GwtEvent; 4 | 5 | public class SetStatusEvent extends GwtEvent { 6 | public static final Type TYPE = new Type(); 7 | private final String statusMessage; 8 | 9 | public SetStatusEvent(final String statusMessage) { 10 | this.statusMessage = statusMessage; 11 | } 12 | 13 | @Override 14 | public final Type getAssociatedType() { 15 | return TYPE; 16 | } 17 | 18 | @Override 19 | protected final void dispatch(final SetStatusEventHandler handler) { 20 | handler.onSetStatus(this); 21 | } 22 | 23 | public final String getStatusMessage() { 24 | return statusMessage; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/astrochart/client/event/SetStatusEventHandler.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.event; 2 | 3 | import com.google.gwt.event.shared.EventHandler; 4 | 5 | public interface SetStatusEventHandler extends EventHandler { 6 | void onSetStatus(final SetStatusEvent event); 7 | } 8 | -------------------------------------------------------------------------------- /src/astrochart/client/presenter/AbstractTabPresenter.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.presenter; 2 | 3 | import com.google.gwt.event.shared.HandlerManager; 4 | import com.google.gwt.user.client.ui.TabPanel; 5 | import com.google.gwt.user.client.ui.Widget; 6 | 7 | public class AbstractTabPresenter { 8 | private final TabPanel tabPanel; 9 | private final HandlerManager eventBus; 10 | 11 | public AbstractTabPresenter(final HandlerManager eventBus, final TabPanel tabPanel) { 12 | this.tabPanel = tabPanel; 13 | this.eventBus = eventBus; 14 | } 15 | 16 | public final Widget getTabPanel() { 17 | return tabPanel; 18 | } 19 | 20 | public final HandlerManager getEventBus() { 21 | return eventBus; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/astrochart/client/presenter/AdminPresenter.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.presenter; 2 | 3 | import java.util.logging.Logger; 4 | import astrochart.client.service.AdminService; 5 | import astrochart.client.service.AdminServiceAsync; 6 | import astrochart.shared.data.Epoch; 7 | import astrochart.shared.enums.Planet; 8 | import astrochart.shared.enums.Weekday; 9 | import astrochart.shared.enums.time.Month; 10 | import com.google.gwt.core.client.GWT; 11 | import com.google.gwt.core.client.Scheduler; 12 | import com.google.gwt.core.client.Scheduler.ScheduledCommand; 13 | import com.google.gwt.event.dom.client.ClickEvent; 14 | import com.google.gwt.event.dom.client.ClickHandler; 15 | import com.google.gwt.i18n.client.DateTimeFormat; 16 | import com.google.gwt.user.client.rpc.AsyncCallback; 17 | import com.google.gwt.user.client.ui.Button; 18 | import com.google.gwt.user.client.ui.HasWidgets; 19 | import com.google.gwt.user.client.ui.Label; 20 | import com.google.gwt.user.client.ui.TextArea; 21 | import com.google.gwt.user.client.ui.Widget; 22 | 23 | public class AdminPresenter implements Presenter { 24 | private static final Logger LOG = Logger.getLogger(AdminPresenter.class.getName()); 25 | private final AdminServiceAsync adminService = GWT.create(AdminService.class); 26 | private final DateTimeFormat format = DateTimeFormat.getFormat("dd MM yyyy HH:mm:ss"); 27 | private final Display display; 28 | 29 | private Month epochMonth = Month.January; 30 | private int epochYear = 0; 31 | private String[] lines; 32 | private int lineIndex; 33 | private int counter; 34 | private boolean hasError = false; 35 | 36 | public interface Display { 37 | Widget asWidget(); 38 | Button getSubmitButton(); 39 | TextArea getInputTextArea(); 40 | Label getStatusLabel(); 41 | Label getSecondStatusLabel(); 42 | } 43 | 44 | public AdminPresenter(final Display view) { 45 | this.display = view; 46 | } 47 | 48 | public final void bind() { 49 | display.getSubmitButton().addClickHandler(new ClickHandler() { 50 | @Override 51 | public final void onClick(final ClickEvent event) { 52 | parseAndSubmitEpochs(); 53 | } 54 | }); 55 | } 56 | 57 | @Override 58 | public final void go(final HasWidgets container) { 59 | bind(); 60 | container.clear(); 61 | container.add(display.asWidget()); 62 | display.getStatusLabel().setText("Ready."); 63 | display.getInputTextArea().setFocus(true); 64 | } 65 | 66 | private void parseAndSubmitEpochs() { 67 | display.getSubmitButton().setEnabled(false); 68 | counter = 0; 69 | lineIndex = 0; 70 | lines = display.getInputTextArea().getText().split("\n"); 71 | hasError = false; 72 | Scheduler.get().scheduleDeferred(new ScheduledCommand() { 73 | @Override 74 | public void execute() { 75 | parseLine(lineIndex); 76 | } 77 | }); 78 | } 79 | 80 | private synchronized void parseLine(final int index) { 81 | if (!hasError) { 82 | display.getStatusLabel().setText("Processing line: " + index); 83 | display.getSecondStatusLabel().setText(epochYear + " " + epochMonth); 84 | for (final Month month : Month.values()) { 85 | if (lines[index].startsWith(month.name().toUpperCase())) { 86 | epochMonth = month; 87 | epochYear = Integer.parseInt(lines[index].split(" ")[1]); 88 | } 89 | } 90 | final Month finalEpochMonth = epochMonth; 91 | final int finalEpochYear = epochYear; 92 | parseEpochLine(finalEpochYear, finalEpochMonth, lines[index]); 93 | if (lineIndex >= lines.length) { 94 | display.getSubmitButton().setEnabled(true); 95 | display.getStatusLabel().setText("Done."); 96 | display.getSecondStatusLabel().setText("Number of Epochs submitted: " + counter); 97 | } else { // next 98 | Scheduler.get().scheduleDeferred(new ScheduledCommand() { 99 | @Override 100 | public void execute() { 101 | parseLine(lineIndex++); 102 | } 103 | }); 104 | } 105 | } else { 106 | display.getSubmitButton().setEnabled(true); 107 | return; 108 | } 109 | } 110 | 111 | private void parseEpochLine(final int epochYear, final Month epochMonth, final String line) { 112 | for (final Weekday weekday : Weekday.values()) { 113 | if (line.startsWith(weekday.getAbbreviation())) { 114 | final String[] split = line.split(" "); 115 | //DATE SID.TIME SUN MOON MERCURY VENUS MARS JUPITER SATURN URANUS NEPTUNE PLUTO NODE 116 | //0 1 2 3 4 5 6 7 8 9 10 11 12 13 117 | //Fr 01 06:42:57 10CP36 07VI24 18CP00 20AQ04 29AR32 21LI12 25LI38 17AR44 17VI18 02TA24 20PI56 118 | 119 | final Epoch epoch = new Epoch(); 120 | final String monthString = addZeroIfNeeded(String.valueOf(epochMonth.getNumber())); 121 | epoch.setSidDate(format.parse( 122 | split[1] + " " + monthString + " " + epochYear + " " + split[2] 123 | )); 124 | epoch.setDay(weekday.getAbbreviation()); 125 | for (final Planet planet : Planet.values()) { 126 | if (!planet.equals(Planet.SouthNode)) { 127 | epoch.setPosition(planet, split[planet.getToken()]); 128 | } 129 | } 130 | submitEpoch(epoch); 131 | } 132 | } 133 | } 134 | 135 | private String addZeroIfNeeded(final String monthString) { 136 | if (monthString.length() == 1) { 137 | return "0" + monthString; 138 | } else { 139 | return monthString; 140 | } 141 | } 142 | 143 | private void submitEpoch(final Epoch epoch) { 144 | adminService.saveEpoch(epoch, new AsyncCallback() { 145 | @Override 146 | public void onSuccess(final Void result) { 147 | counter++; 148 | } 149 | @Override 150 | public void onFailure(final Throwable caught) { 151 | hasError = true; 152 | LOG.severe("Fail submitting Epoch: " + caught.getMessage()); 153 | LOG.severe("Year: " + epochYear + " Month: " + epochMonth + " Epoch: " + epoch); 154 | display.getStatusLabel().setText("Fail submitting Epoch: " + caught.getMessage()); 155 | display.getSecondStatusLabel().setText("Year: " + epochYear + " Month: " + epochMonth + " Epoch: " + epoch); 156 | } 157 | }); 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/astrochart/client/presenter/ChartPresenter.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.presenter; 2 | 3 | import java.util.Date; 4 | import astrochart.client.event.DateUpdatedEvent; 5 | import astrochart.client.event.DateUpdatedEventHandler; 6 | import astrochart.client.event.ResetAspectsEvent; 7 | import astrochart.client.event.ResetAspectsEventHandler; 8 | import astrochart.client.event.SetStatusEvent; 9 | import astrochart.client.event.SetStatusEventHandler; 10 | import astrochart.client.service.EpochService; 11 | import astrochart.client.service.EpochServiceAsync; 12 | import astrochart.client.service.GeocodeService; 13 | import astrochart.client.service.GeocodeServiceAsync; 14 | import astrochart.client.util.AstrologyUtil; 15 | import astrochart.client.util.DateTimeUtil; 16 | import astrochart.client.widgets.Chart; 17 | import astrochart.client.widgets.TimeEntry; 18 | import astrochart.shared.data.Epoch; 19 | import astrochart.shared.data.GeocodeData; 20 | import astrochart.shared.enums.AspectType; 21 | import astrochart.shared.enums.HouseType; 22 | import astrochart.shared.enums.Planet; 23 | import astrochart.shared.exceptions.EpochNotFoundException; 24 | import astrochart.shared.wrappers.AscendentAndOffset; 25 | import astrochart.shared.wrappers.BodyPosition; 26 | import astrochart.shared.wrappers.RiseAndSet; 27 | import com.google.gwt.core.client.Callback; 28 | import com.google.gwt.core.client.GWT; 29 | import com.google.gwt.core.client.Scheduler; 30 | import com.google.gwt.core.client.Scheduler.ScheduledCommand; 31 | import com.google.gwt.event.dom.client.ChangeEvent; 32 | import com.google.gwt.event.dom.client.ChangeHandler; 33 | import com.google.gwt.event.dom.client.ClickEvent; 34 | import com.google.gwt.event.dom.client.ClickHandler; 35 | import com.google.gwt.event.dom.client.KeyCodes; 36 | import com.google.gwt.event.dom.client.KeyUpEvent; 37 | import com.google.gwt.event.dom.client.KeyUpHandler; 38 | import com.google.gwt.event.logical.shared.ValueChangeEvent; 39 | import com.google.gwt.event.logical.shared.ValueChangeHandler; 40 | import com.google.gwt.event.shared.HandlerManager; 41 | import com.google.gwt.geolocation.client.Geolocation; 42 | import com.google.gwt.geolocation.client.Position; 43 | import com.google.gwt.geolocation.client.Position.Coordinates; 44 | import com.google.gwt.geolocation.client.PositionError; 45 | import com.google.gwt.i18n.client.NumberFormat; 46 | import com.google.gwt.user.client.rpc.AsyncCallback; 47 | import com.google.gwt.user.client.ui.Button; 48 | import com.google.gwt.user.client.ui.CheckBox; 49 | import com.google.gwt.user.client.ui.HasWidgets; 50 | import com.google.gwt.user.client.ui.Label; 51 | import com.google.gwt.user.client.ui.ListBox; 52 | import com.google.gwt.user.client.ui.TabPanel; 53 | import com.google.gwt.user.client.ui.TextBox; 54 | import com.google.gwt.user.client.ui.Widget; 55 | 56 | public class ChartPresenter extends AbstractTabPresenter implements Presenter { 57 | private final EpochServiceAsync epochService = GWT.create(EpochService.class); 58 | private final GeocodeServiceAsync geocodeService = GWT.create(GeocodeService.class); 59 | private final AstrologyUtil astroUtil = new AstrologyUtil(); 60 | private final DateTimeUtil dateTimeUtil; 61 | private final Display display; 62 | private Date providedUtcDate; 63 | private Epoch epoch; 64 | private Date localDate; 65 | private Date utcDate; 66 | private boolean disableUpdate = false; 67 | 68 | public interface Display { 69 | Widget asWidget(); 70 | Button getUpdatePositionsButton(); 71 | Button getRegenerateChartButton(); 72 | Chart getChart(); 73 | Label getUtcLabel(); 74 | Label getUtcJdLabel(); 75 | Label getUtcSidLabel(); 76 | CheckBox getPlanetCheckBox(Planet planet); 77 | Label getPlanetLabel(Planet planet); 78 | Button getSelectAllPlanetsButton(); 79 | Button getUnselectAllPlanetsButton(); 80 | ListBox getHousesListBox(); 81 | CheckBox getAspectCheckBox(AspectType type); 82 | ListBox getAspectListBox(AspectType type); 83 | Label getAspectLabel(AspectType type); 84 | void resetAspects(); 85 | Button resetOrbsButton(); 86 | void resetOrbs(); 87 | Button getSelectAllAspectsButton(); 88 | Button getUnselectAllAspectsButton(); 89 | TextBox getLocationTextBox(); 90 | Button getSubmitCityButton(); 91 | TextBox getLatitudeTextBox(); 92 | Button getSubmitLatitudeButton(); 93 | TextBox getLongitudeTextBox(); 94 | Button getSubmitLongitudeButton(); 95 | Label getSunriseLabel(); 96 | Label getSunsetLabel(); 97 | Label getAscendentLabel(); 98 | Label getStatusLabel(); 99 | Label getSunPositionLabel(); 100 | TimeEntry getTimeEntry(); 101 | } 102 | 103 | public ChartPresenter(final HandlerManager eventBus, final DateTimeUtil dateTimeUtil, final TabPanel tabPanel, final Display view, 104 | final Date providedUtcDate) { 105 | super(eventBus, tabPanel); 106 | this.dateTimeUtil = dateTimeUtil; 107 | this.providedUtcDate = providedUtcDate; 108 | this.display = view; 109 | } 110 | 111 | public final void bind() { 112 | bindBus(); 113 | this.display.getUpdatePositionsButton().addClickHandler(new ClickHandler() { 114 | @Override 115 | public void onClick(final ClickEvent event) { 116 | updateEpoch(); 117 | } 118 | }); 119 | this.display.getRegenerateChartButton().addClickHandler(new ClickHandler() { 120 | @Override 121 | public void onClick(final ClickEvent event) { 122 | regenerateChart(); 123 | } 124 | }); 125 | for (final Planet planet : Planet.values()) { 126 | this.display.getPlanetCheckBox(planet).addValueChangeHandler(createDefaultValueChangeHandler()); 127 | } 128 | this.display.getSelectAllPlanetsButton().addClickHandler(createPlanetsChangeHandler(true)); 129 | this.display.getUnselectAllPlanetsButton().addClickHandler(createPlanetsChangeHandler(false)); 130 | this.display.getHousesListBox().addChangeHandler(new ChangeHandler() { 131 | @Override 132 | public void onChange(final ChangeEvent event) { 133 | final String houseSystemName = display.getHousesListBox().getItemText(display.getHousesListBox().getSelectedIndex()); 134 | final HouseType type = HouseType.getTypeForName(houseSystemName); 135 | display.getChart().changeHouseSystem(type); 136 | } 137 | }); 138 | for (final AspectType type : AspectType.values()) { 139 | this.display.getAspectCheckBox(type).addValueChangeHandler(createDefaultValueChangeHandler()); 140 | this.display.getAspectListBox(type).addChangeHandler(new ChangeHandler() { 141 | @Override 142 | public void onChange(final ChangeEvent event) { 143 | regenerateChart(); 144 | } 145 | }); 146 | } 147 | this.display.resetOrbsButton().addClickHandler(new ClickHandler() { 148 | @Override 149 | public void onClick(final ClickEvent event) { 150 | disableUpdate = true; 151 | display.resetOrbs(); 152 | disableUpdate = false; 153 | regenerateChart(); 154 | 155 | } 156 | }); 157 | this.display.getSelectAllAspectsButton().addClickHandler(createAspectChangeHandler(true)); 158 | this.display.getUnselectAllAspectsButton().addClickHandler(createAspectChangeHandler(false)); 159 | this.display.getLocationTextBox().addKeyUpHandler(new KeyUpHandler() { 160 | @Override 161 | public void onKeyUp(final KeyUpEvent event) { 162 | if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { 163 | updateGeodataByCityName(); 164 | } 165 | } 166 | }); 167 | this.display.getSubmitCityButton().addClickHandler(new ClickHandler() { 168 | @Override 169 | public void onClick(final ClickEvent event) { 170 | updateGeodataByCityName(); 171 | } 172 | }); 173 | this.display.getSubmitLatitudeButton().addClickHandler(createGeocodeClickHandler()); 174 | this.display.getSubmitLongitudeButton().addClickHandler(createGeocodeClickHandler()); 175 | this.display.getLatitudeTextBox().addKeyUpHandler(createGeocodeKeyUpHandler()); 176 | this.display.getLongitudeTextBox().addKeyUpHandler(createGeocodeKeyUpHandler()); 177 | } 178 | 179 | public final void bindBus() { 180 | getEventBus().addHandler(DateUpdatedEvent.TYPE, new DateUpdatedEventHandler() { 181 | @Override 182 | public void onDateUpdated(final DateUpdatedEvent event) { 183 | updateEpoch(event.getLocalDate()); 184 | } 185 | }); 186 | getEventBus().addHandler(ResetAspectsEvent.TYPE, new ResetAspectsEventHandler() { 187 | @Override 188 | public void onResetAspects(final ResetAspectsEvent event) { 189 | display.resetAspects(); 190 | } 191 | }); 192 | getEventBus().addHandler(SetStatusEvent.TYPE, new SetStatusEventHandler() { 193 | @Override 194 | public void onSetStatus(final SetStatusEvent event) { 195 | display.getStatusLabel().setText(event.getStatusMessage()); 196 | } 197 | }); 198 | } 199 | 200 | @Override 201 | public final void go(final HasWidgets container) { 202 | bind(); 203 | container.clear(); 204 | container.add(super.getTabPanel()); 205 | if (providedUtcDate != null) { 206 | // fill time entry with provided date (calls updateEpoch) 207 | display.getTimeEntry().updateDate(providedUtcDate); 208 | } else { 209 | updateEpoch(); 210 | } 211 | 212 | // XXX Experimental HTML5 Geolocation 213 | // tryToGetGeolocationFromBrowser(); 214 | 215 | if (display.getLocationTextBox().getText().equals("unknown")) { 216 | updateGeodataByIp(); 217 | } 218 | this.display.getLocationTextBox().setFocus(true); 219 | } 220 | 221 | private void updateEpoch() { 222 | updateEpoch(null); 223 | } 224 | 225 | private void updateEpoch(final Date inputLocalDate) { 226 | display.getStatusLabel().setText("Updating positions."); 227 | if (inputLocalDate != null) { 228 | localDate = inputLocalDate; 229 | } else { 230 | localDate = display.getTimeEntry().getLocalDate(); 231 | } 232 | utcDate = dateTimeUtil.getUtcDate(localDate); 233 | final String timeZone = display.getTimeEntry().getClientTimezone(); 234 | display.getUtcLabel().setText(dateTimeUtil.formatDateAsUtc(localDate)); 235 | display.getUtcLabel().setTitle("As Time in your local timezone: \n" + dateTimeUtil.formatLocalDate(utcDate) + timeZone); 236 | display.getUtcJdLabel().setText(dateTimeUtil.getFormattedJdTimeDate(utcDate)); 237 | display.getUtcJdLabel().setTitle("As JD Time in your local timezone: \n" + dateTimeUtil.getFormattedJdTimeDate(localDate) + timeZone); 238 | final Date sidDate = dateTimeUtil.getLocalSidTimeDate(localDate); // also known as LST 239 | final Date utcSidDate = dateTimeUtil.getLocalSidTimeDate(utcDate); // also known as GMST 240 | display.getUtcSidLabel().setTitle("As Sidereal Time in your local timezone: \n" + dateTimeUtil.formatLocalDate(sidDate) + timeZone); 241 | display.getUtcSidLabel().setText(dateTimeUtil.formatLocalDate(utcSidDate)); 242 | epochService.readEpoch(utcSidDate, new AsyncCallback() { 243 | @Override 244 | public void onSuccess(final Epoch result) { 245 | epoch = result; 246 | for (final Planet planet : Planet.values()) { 247 | final Label label = display.getPlanetLabel(planet); 248 | label.setText(result.getPositionDegreeString(planet)); 249 | label.setTitle(result.getPositionString(planet)); 250 | } 251 | display.getStatusLabel().setText("Positions updated."); 252 | processCustomGeocode(false); 253 | } 254 | 255 | @Override 256 | public void onFailure(final Throwable caught) { 257 | if (caught instanceof EpochNotFoundException) { 258 | display.getStatusLabel().setText("Epoch not found. Please try another date."); 259 | } else { 260 | display.getStatusLabel().setText("Fail reading epoch: " + caught.getMessage()); 261 | } 262 | } 263 | }); 264 | } 265 | 266 | /** 267 | * Experimental HTML5 feature 268 | */ 269 | @SuppressWarnings("unused") 270 | private void tryToGetGeolocationFromBrowser() { 271 | final Geolocation geolocation = Geolocation.getIfSupported(); // experimental 272 | geolocation.getCurrentPosition(new Callback() { 273 | @Override 274 | public void onSuccess(final Position result) { 275 | final Coordinates coords = result.getCoordinates(); 276 | display.getLatitudeTextBox().setText(String.valueOf(coords.getLatitude())); 277 | display.getLatitudeTextBox().setTitle(astroUtil.convertDegrees(coords.getLatitude())); 278 | display.getLongitudeTextBox().setText(String.valueOf(coords.getLongitude())); 279 | display.getLongitudeTextBox().setTitle(astroUtil.convertDegrees(coords.getLongitude())); 280 | processCustomGeocode(true); 281 | } 282 | 283 | @Override 284 | public void onFailure(final PositionError reason) { 285 | display.getStatusLabel().setText("Fail: Not able to get geolocation data from browser."); 286 | } 287 | }); 288 | } 289 | 290 | private void updateGeodataByIp() { 291 | display.getStatusLabel().setText("Updating geodata by IP."); 292 | geocodeService.getGeocodeDataForIp(new AsyncCallback() { 293 | @Override 294 | public void onSuccess(final GeocodeData result) { 295 | processGeocodeData(result); 296 | } 297 | @Override 298 | public void onFailure(final Throwable caught) { 299 | display.getStatusLabel().setText( 300 | "Fail: Getting geocode data from IP. Please enter a city name or provide the latitude and longitude manually."); 301 | } 302 | }); 303 | } 304 | 305 | private void updateGeodataByCityName() { 306 | display.getStatusLabel().setText("Updating geodata by location name."); 307 | final String cityName = display.getLocationTextBox().getText().trim(); 308 | geocodeService.getGeocodeData(cityName, new AsyncCallback() { 309 | @Override 310 | public void onSuccess(final GeocodeData result) { 311 | processGeocodeData(result); 312 | } 313 | @Override 314 | public void onFailure(final Throwable caught) { 315 | display.getStatusLabel().setText("Fail: Getting geocode data."); 316 | } 317 | }); 318 | } 319 | 320 | private void processCustomGeocode(final boolean resetCityName) { 321 | display.getStatusLabel().setText("Processing custom geocode data."); 322 | final GeocodeData geocode = new GeocodeData(); 323 | if (resetCityName) { 324 | geocode.setCityName("user input"); 325 | this.display.getLocationTextBox().setText("user input"); 326 | } else { 327 | geocode.setCityName(display.getLocationTextBox().getText()); 328 | } 329 | this.display.getStatusLabel().setText(""); 330 | try { 331 | geocode.setLatitude(Double.valueOf(display.getLatitudeTextBox().getText())); 332 | try { 333 | geocode.setLongitude(Double.valueOf(display.getLongitudeTextBox().getText())); 334 | processGeocodeData(geocode); 335 | } catch (final NumberFormatException nfe) { 336 | final String message = "Fail: Longitude is not numeric."; 337 | this.display.getStatusLabel().setText(message); 338 | this.display.getLongitudeTextBox().setFocus(true); 339 | } 340 | } catch (final NumberFormatException nfe) { 341 | final String message = "Fail: Latitide is not numeric."; 342 | this.display.getStatusLabel().setText(message); 343 | this.display.getLatitudeTextBox().setFocus(true); 344 | } 345 | } 346 | 347 | private void processGeocodeData(final GeocodeData geocode) { 348 | if (geocode == null || (geocode.getCityName().equals("") && geocode.getLatitude() == 0.0D && geocode.getLongitude() == 0.0D)) { 349 | assert true; // ignore 350 | } else { 351 | display.getLocationTextBox().setText(geocode.getCityName()); 352 | 353 | final NumberFormat nf = NumberFormat.getFormat("0.0000000"); 354 | display.getLatitudeTextBox().setTitle(astroUtil.convertDegrees(geocode.getLatitude())); 355 | display.getLatitudeTextBox().setText(nf.format(geocode.getLatitude())); 356 | display.getLongitudeTextBox().setTitle(astroUtil.convertDegrees(geocode.getLongitude())); 357 | display.getLongitudeTextBox().setText(nf.format(geocode.getLongitude())); 358 | 359 | final RiseAndSet ras = astroUtil.calculateSunRiseAndSet(localDate, geocode.getLatitude(), geocode.getLongitude()); 360 | display.getSunriseLabel().setText(dateTimeUtil.formatLocalDate(ras.getRise())); 361 | display.getSunsetLabel().setText(dateTimeUtil.formatLocalDate(ras.getSet())); 362 | final BodyPosition position = astroUtil.calculateSunPosition(utcDate, geocode.getLatitude(), geocode.getLongitude()); 363 | display.getSunPositionLabel().setText(position.toString()); 364 | 365 | final AscendentAndOffset ascendent = astroUtil.determineAscendent(utcDate, geocode.getLongitude(), geocode.getLatitude()); 366 | display.getAscendentLabel().setText(ascendent.toString()); 367 | 368 | display.getStatusLabel().setText("Generating chart..."); 369 | Scheduler.get().scheduleDeferred(new ScheduledCommand() { 370 | @Override 371 | public void execute() { 372 | final String houseSystemName = display.getHousesListBox().getItemText(display.getHousesListBox().getSelectedIndex()); 373 | final HouseType type = HouseType.getTypeForName(houseSystemName); 374 | display.getChart().generateChart(ascendent, epoch, type); 375 | } 376 | }); 377 | } 378 | } 379 | 380 | public final void regenerateChart() { 381 | if (disableUpdate) { 382 | return; 383 | } 384 | display.getStatusLabel().setText("Generating chart..."); 385 | Scheduler.get().scheduleDeferred(new ScheduledCommand() { 386 | @Override 387 | public void execute() { 388 | processCustomGeocode(false); 389 | } 390 | }); 391 | } 392 | 393 | private ClickHandler createAspectChangeHandler(final boolean value) { 394 | return new ClickHandler() { 395 | @Override 396 | public void onClick(final ClickEvent event) { 397 | disableUpdate = true; 398 | for (final AspectType aspectType : AspectType.values()) { 399 | display.getAspectCheckBox(aspectType).setValue(value); 400 | } 401 | disableUpdate = false; 402 | regenerateChart(); 403 | } 404 | }; 405 | } 406 | 407 | private ClickHandler createPlanetsChangeHandler(final boolean value) { 408 | return new ClickHandler() { 409 | @Override 410 | public void onClick(final ClickEvent event) { 411 | disableUpdate = true; 412 | for (final Planet planet : Planet.values()) { 413 | display.getPlanetCheckBox(planet).setValue(value); 414 | } 415 | disableUpdate = false; 416 | regenerateChart(); 417 | } 418 | }; 419 | } 420 | 421 | private ValueChangeHandler createDefaultValueChangeHandler() { 422 | return new ValueChangeHandler() { 423 | @Override 424 | public void onValueChange(final ValueChangeEvent event) { 425 | regenerateChart(); 426 | } 427 | }; 428 | } 429 | 430 | private ClickHandler createGeocodeClickHandler() { 431 | return new ClickHandler() { 432 | @Override 433 | public void onClick(final ClickEvent event) { 434 | processCustomGeocode(true); 435 | } 436 | }; 437 | } 438 | 439 | private KeyUpHandler createGeocodeKeyUpHandler() { 440 | return new KeyUpHandler() { 441 | @Override 442 | public void onKeyUp(final KeyUpEvent event) { 443 | if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { 444 | processCustomGeocode(true); 445 | } 446 | } 447 | }; 448 | } 449 | } 450 | -------------------------------------------------------------------------------- /src/astrochart/client/presenter/InfoPresenter.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.presenter; 2 | 3 | import com.google.gwt.event.shared.HandlerManager; 4 | import com.google.gwt.user.client.ui.Anchor; 5 | import com.google.gwt.user.client.ui.FlexTable; 6 | import com.google.gwt.user.client.ui.HTML; 7 | import com.google.gwt.user.client.ui.HasWidgets; 8 | import com.google.gwt.user.client.ui.TabPanel; 9 | import com.google.gwt.user.client.ui.Widget; 10 | 11 | public class InfoPresenter extends AbstractTabPresenter implements Presenter { 12 | private final Display display; 13 | private int row = 0; 14 | 15 | public interface Display { 16 | FlexTable getInfoList(); 17 | Widget asWidget(); 18 | } 19 | 20 | public InfoPresenter(final HandlerManager eventBus, 21 | final TabPanel tabPanel, final Display view) { 22 | super(eventBus, tabPanel); 23 | this.display = view; 24 | } 25 | 26 | public final void bind() { 27 | } 28 | 29 | @Override 30 | public final void go(final HasWidgets container) { 31 | bind(); 32 | prepareTable(); 33 | container.clear(); 34 | container.add(super.getTabPanel()); 35 | } 36 | 37 | private void prepareTable() { 38 | display.getInfoList().removeAllRows(); 39 | display.getInfoList().getColumnFormatter().setWidth(0, "100px"); 40 | addRowText("Welcome to Astrology Chart Generator."); 41 | addRowText("This application is work in progress and may therefore still display incorrect results."); 42 | addRowWidget(new HTML(" ")); 43 | addRowText("The ephemeris used in this application can be found at:"); 44 | addRowWidget(new Anchor("http://www.findyourfate.com/astrology/ephemeris/ephemeris.html", "http://www.findyourfate.com/astrology/ephemeris/ephemeris.html")); 45 | addRowWidget(new HTML(" ")); 46 | addRowText("Astrology Chart Generator uses the following IP-location lookup service:"); 47 | addRowWidget(new Anchor("http://freegeoip.net", "http://freegeoip.net")); 48 | addRowWidget(new HTML(" ")); 49 | addRowText("The location lookup by city-name is powered by:"); 50 | addRowWidget(new Anchor("http://code.google.com/apis/maps/index.html", "http://code.google.com/apis/maps/index.html")); 51 | addRowWidget(new HTML(" ")); 52 | addRowText("Sunrise and sunset calculations are done according to the formulas provided at:"); 53 | addRowWidget(new Anchor("http://users.electromagnetic.net/bu/astro/sunrise-set.php", "http://users.electromagnetic.net/bu/astro/sunrise-set.php")); 54 | addRowText("This application will therefore calculate the same results for sunrise and sunset as calculated here:"); 55 | addRowWidget(new Anchor("http://users.electromagnetic.net/bu/astro/iyf-calc.php", "http://users.electromagnetic.net/bu/astro/iyf-calc.php")); 56 | addRowText("(Beware: There are many other online calculators that result in different results.)"); 57 | addRowWidget(new HTML(" ")); 58 | addRowText("The source code and the unit tests of this application can be found at:"); 59 | addRowWidget(new Anchor("https://github.com/Tok/AstroChart", "https://github.com/Tok/AstroChart")); 60 | } 61 | 62 | private void addRowText(final String text) { 63 | display.getInfoList().setText(row, 0, text); 64 | row++; 65 | } 66 | 67 | private void addRowWidget(final Widget widget) { 68 | display.getInfoList().setWidget(row, 0, widget); 69 | row++; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/astrochart/client/presenter/Presenter.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.presenter; 2 | 3 | import com.google.gwt.user.client.ui.HasWidgets; 4 | 5 | public abstract interface Presenter { 6 | void go(final HasWidgets container); 7 | } 8 | -------------------------------------------------------------------------------- /src/astrochart/client/service/AdminService.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.service; 2 | 3 | import astrochart.shared.data.Epoch; 4 | import com.google.gwt.user.client.rpc.RemoteService; 5 | import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; 6 | 7 | @RemoteServiceRelativePath("admin") 8 | public interface AdminService extends RemoteService { 9 | void saveEpoch(final Epoch epoch); 10 | } 11 | -------------------------------------------------------------------------------- /src/astrochart/client/service/AdminServiceAsync.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.service; 2 | 3 | import astrochart.shared.data.Epoch; 4 | import com.google.gwt.user.client.rpc.AsyncCallback; 5 | 6 | public interface AdminServiceAsync { 7 | void saveEpoch(final Epoch epoch, final AsyncCallback callback);; 8 | } 9 | -------------------------------------------------------------------------------- /src/astrochart/client/service/EpochService.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.service; 2 | 3 | import java.util.Date; 4 | import astrochart.shared.data.Epoch; 5 | import astrochart.shared.exceptions.EpochNotFoundException; 6 | import com.google.gwt.user.client.rpc.RemoteService; 7 | import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; 8 | 9 | @RemoteServiceRelativePath("epoch") 10 | public interface EpochService extends RemoteService { 11 | Epoch readEpoch(final Date date) throws EpochNotFoundException; 12 | } 13 | -------------------------------------------------------------------------------- /src/astrochart/client/service/EpochServiceAsync.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.service; 2 | 3 | import java.util.Date; 4 | import astrochart.shared.data.Epoch; 5 | import com.google.gwt.user.client.rpc.AsyncCallback; 6 | 7 | public interface EpochServiceAsync { 8 | void readEpoch(final Date date, final AsyncCallback callback); 9 | } 10 | -------------------------------------------------------------------------------- /src/astrochart/client/service/GeocodeService.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.service; 2 | 3 | import astrochart.shared.data.GeocodeData; 4 | import com.google.gwt.user.client.rpc.RemoteService; 5 | import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; 6 | 7 | @RemoteServiceRelativePath("geocode") 8 | public interface GeocodeService extends RemoteService { 9 | GeocodeData getGeocodeData(final String cityName); 10 | GeocodeData getGeocodeDataForIp(); 11 | } 12 | -------------------------------------------------------------------------------- /src/astrochart/client/service/GeocodeServiceAsync.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.service; 2 | 3 | import astrochart.shared.data.GeocodeData; 4 | import com.google.gwt.user.client.rpc.AsyncCallback; 5 | 6 | public interface GeocodeServiceAsync { 7 | void getGeocodeData(final String cityName, final AsyncCallback callback); 8 | void getGeocodeDataForIp(final AsyncCallback callback);; 9 | } 10 | -------------------------------------------------------------------------------- /src/astrochart/client/util/Constants.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.util; 2 | 3 | public final class Constants { 4 | public static final double JULIAN_DAY_AT_01_01_2000 = 2451545D; 5 | public static final double HALF_JULIAN_DAY = 0.5D; 6 | public static final double MEAN_LONGITUDE_OF_THE_SUN = 280.460D; // XXX sometimes given as 280.461 7 | public static final double MEAN_LONGITUDE_OF_THE_SUN_PRECISE = 280.46061837D; 8 | public static final double DEGREES_IN_CIRCLE = 360.0D; 9 | public static final double DEGREES_PER_HOUR = 15D; 10 | public static final double MINUTES_PER_DEGREE = 60.0D; 11 | public static final double HOURS_PER_DAY = 24D; 12 | public static final double MINUTES_PER_HOUR = 60D; 13 | public static final double SECONDS_PER_MINUTE = 60D; 14 | public static final double SECONDS_PER_HOUR = 3600D; 15 | public static final long MILLISECONDS_PER_MINUTE = 60000L; 16 | public static final long MILLISECONDS_PER_DAY = 86400000L; 17 | public static final char DEGREE_SIGN = '\u00B0'; 18 | public static final char MINUTE_SIGN = '\u2032'; 19 | public static final char SECOND_SIGN = '\u2033'; 20 | 21 | private Constants() { } 22 | } 23 | -------------------------------------------------------------------------------- /src/astrochart/client/util/DateTimeUtil.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.util; 2 | 3 | import java.util.Date; 4 | import com.google.gwt.i18n.client.DateTimeFormat; 5 | import com.google.gwt.i18n.client.NumberFormat; 6 | import com.google.gwt.i18n.client.TimeZone; 7 | 8 | public class DateTimeUtil { 9 | public static final double J_CONSTANT = 2451545.0009D; 10 | private static final long MS_2000 = 946684800000L; //2000-01-01 00:00:00 +0000 in milliseconds 11 | private static final double JD_2000 = Constants.JULIAN_DAY_AT_01_01_2000 - Constants.HALF_JULIAN_DAY; //2000-01-01 00:00:00 as JD 12 | private static final long MS_PER_DAY = 86400000L; 13 | private static final double DAYS_PER_YEAR = 365D; 14 | private static final long MONTHS_PER_YEAR = 12L; 15 | private static final double DAYS_PER_JULIAN_CENTURY = 36525D; 16 | private static final double MINUTES_PER_DAY = 1440D; 17 | private static final double SECONDS_PER_HOUR = 3600D; 18 | private static final double SECONDS_PER_DAY = 86400D; 19 | private static final double SIDEREAL_CONSTANT_1 = 13185000.77D; 20 | private static final double SIDEREAL_CONSTANT_2 = 2577.765D; 21 | private static final double SIDEREAL_CONSTANT_3 = 38710000D; 22 | private static final double SIDEREAL_GMST_CONSTANT_0 = 24110.54841D; 23 | private static final double SIDEREAL_GMST_CONSTANT_1 = 8640184.812866D; 24 | private static final double SIDEREAL_GMST_CONSTANT_2 = 0.093104D; 25 | private static final double SIDEREAL_GMST_CONSTANT_3 = 0.0000062D; 26 | private static final double SIDEREAL_HOUR_CONSTANT_1 = 18.697374558D; 27 | private static final double SIDEREAL_HOUR_CONSTANT_2 = 24.06570982441908D; 28 | private static final double GMST_HOUR_CONSTANT_1 = 6.697374558D; 29 | private static final double GMST_HOUR_CONSTANT_2 = 0.06570982441908D; 30 | private static final double GMST_HOUR_CONSTANT_3 = 1.00273790935D; 31 | private static final double GMST_HOUR_CONSTANT_4 = 0.000026D; 32 | private static final double STARTIME_CONSTANT_1 = 6.697376D; //change to GMST_HOUR_CONSTANT_1? 33 | private static final double STARTIME_CONSTANT_2 = 2400.05134D; 34 | private static final double STARTIME_CONSTANT_3 = 1.002738D; 35 | private static final long LEAP_YEAR_CONSTANT_4 = 4L; 36 | private static final long LEAP_YEAR_CONSTANT_100 = 100L; 37 | private static final long LEAP_YEAR_CONSTANT_400 = 400L; 38 | private static final long JULIAN_DAY_0_BC = 4800L; 39 | private static final long MONTH_FACTOR = 153L; 40 | private static final long JDN_OFFSET = 32045L; 41 | 42 | private final DateTimeFormat dateTimeFormat = DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss"); 43 | private final NumberFormat nf = NumberFormat.getFormat("00"); //number format for hours, minutes or seconds 44 | private final NumberFormat jdNf = NumberFormat.getFormat("0.0000"); //number format for JD 45 | 46 | private enum DateTimeRange { 47 | Year(0, 4), 48 | Month(5, 7), 49 | Days(8, 10), 50 | Hours(11, 13), 51 | Minutes(14, 16), 52 | Seconds(17, 19); 53 | 54 | private int from; 55 | private int to; 56 | 57 | DateTimeRange(final int from, final int to) { 58 | this.from = from; 59 | this.to = to; 60 | } 61 | 62 | public final int getFrom() { 63 | return from; 64 | } 65 | 66 | public final int getTo() { 67 | return to; 68 | } 69 | } 70 | 71 | public final String formatDateAsUtc(final Date localDate) { 72 | return dateTimeFormat.format(localDate, TimeZone.createTimeZone(0)); 73 | } 74 | 75 | public final String formatLocalDate(final Date localDate) { 76 | return dateTimeFormat.format(localDate); 77 | } 78 | 79 | public final String formatLocalDate(final Date localDate, final String timeZone) { 80 | final int timeZoneMinutes = getTimeZoneMinutes(timeZone); 81 | return dateTimeFormat.format(localDate, TimeZone.createTimeZone(timeZoneMinutes)); 82 | } 83 | 84 | private int getTimeZoneMinutes(final String timeZone) { 85 | if (timeZone.contains("+")) { 86 | return Double.valueOf(Double.valueOf(timeZone.split("\\+")[1]) * Constants.MINUTES_PER_HOUR).intValue(); 87 | } else if (timeZone.contains("-")) { 88 | return Double.valueOf(Double.valueOf(timeZone.split("\\-")[1]) * Constants.MINUTES_PER_HOUR).intValue(); 89 | } else { 90 | return 0; 91 | } 92 | } 93 | 94 | public final Date getUtcDate(final Date localDate) { 95 | return dateTimeFormat.parse(formatDateAsUtc(localDate)); 96 | } 97 | 98 | public final Date getUtcDateFromUtcString(final String utcDateString) { 99 | return dateTimeFormat.parse(utcDateString); 100 | } 101 | 102 | public final Date getLocalDateFromUtc(final Date providedUtcDate) { 103 | return dateTimeFormat.parse(dateTimeFormat.format(providedUtcDate)); 104 | } 105 | 106 | /** 107 | * http://en.wikipedia.org/wiki/Julian_day#Julian_Date 108 | * @param date 109 | * @return Julian Date 110 | */ 111 | public final double getJdTimeDate(final Date date) { 112 | final long differenceMs = date.getTime() - new Date(MS_2000).getTime(); //milliseconds since 2000-01-01 00:00:00 113 | final double daysSince2000 = differenceMs / Double.valueOf(MS_PER_DAY); 114 | final double jd = JD_2000 + daysSince2000; //Julian Date 115 | return jd; 116 | } 117 | 118 | public final Date convertJdToDate(final double jd) { 119 | final double daysSince2000 = jd - JD_2000; 120 | final double differenceMs = daysSince2000 * Double.valueOf(MS_PER_DAY); 121 | final long dateMs = Double.valueOf(differenceMs).longValue() + new Date(MS_2000).getTime(); 122 | final Date result = new Date(dateMs); 123 | return result; 124 | } 125 | 126 | public final String getFormattedJdTimeDate(final Date date) { 127 | return jdNf.format(getJdTimeDate(date)); 128 | } 129 | 130 | // /** 131 | // * Also known as GMST 132 | // * @param localDate 133 | // * @return 134 | // */ 135 | // public final Date getGmtSidTimeDate(final Date localDate) { 136 | // return getLocalSidTimeDate(getUtcDate(localDate)); 137 | // } 138 | 139 | /** 140 | * Also known as LST 141 | * http://en.wikipedia.org/wiki/Sidereal_time 142 | * @param date 143 | * @return 144 | */ 145 | public final Date getLocalSidTimeDate(final Date date) { 146 | final double jd = getJdTimeDate(date); 147 | final double a = clampA(getSiderealDegrees(jd) / Constants.DEGREES_PER_HOUR); 148 | 149 | final double gmstHours = a % Constants.HOURS_PER_DAY; 150 | final double gmstMinutes = ((a % Constants.HOURS_PER_DAY) * Constants.MINUTES_PER_HOUR) % Constants.MINUTES_PER_HOUR; 151 | final double gmstSeconds = ((a % Constants.HOURS_PER_DAY) * Constants.MINUTES_PER_HOUR * Constants.SECONDS_PER_MINUTE) 152 | % Constants.SECONDS_PER_MINUTE; 153 | 154 | final String dateString = dateTimeFormat.format(date); 155 | final int dateYear = Integer.valueOf(dateString.substring(0, 4)); 156 | final int dateMonth = Integer.valueOf(dateString.substring(5, 7)); 157 | final int dateDay = Integer.valueOf(dateString.substring(8, 10)); 158 | 159 | final String gmstHoursString = nf.format(Math.floor(gmstHours)); 160 | final String gmstMinutesString = nf.format(Math.floor(gmstMinutes)); 161 | final String gmstSecondsString = nf.format(Math.floor(gmstSeconds)); 162 | 163 | final String gmstDateString = 164 | nf.format(dateYear) + "." + nf.format(dateMonth) + "." + nf.format(dateDay) + " " 165 | + gmstHoursString + ":" + gmstMinutesString + ":" + gmstSecondsString; 166 | 167 | return dateTimeFormat.parse(gmstDateString); 168 | } 169 | 170 | private double clampA(final double a) { 171 | if (a < 0D) { 172 | return Constants.DEGREES_IN_CIRCLE - (Math.abs(a) % Constants.DEGREES_IN_CIRCLE); 173 | } else { 174 | return a; 175 | } 176 | } 177 | 178 | /** 179 | * http://www.cv.nrao.edu/~rfisher/Ephemerides/times.html 180 | * @param jd 181 | * @return GmstSiderealSeconds 182 | */ 183 | @Deprecated 184 | public final double getGmstSeconds(final double jd) { 185 | final double julianCenturiesSinceJ2000 = getJulianCenturiesSinceJ2000(jd); 186 | final double gmstSiderealSeconds = 187 | SIDEREAL_GMST_CONSTANT_0 188 | + (SIDEREAL_GMST_CONSTANT_1 * julianCenturiesSinceJ2000) 189 | + (SIDEREAL_GMST_CONSTANT_2 * Math.pow(julianCenturiesSinceJ2000, 2)) 190 | - (SIDEREAL_GMST_CONSTANT_3 * Math.pow(julianCenturiesSinceJ2000, 3)); 191 | return gmstSiderealSeconds; 192 | } 193 | 194 | /** 195 | * http://answers.yahoo.com/question/index?qid=20070830185150AAoNT4i 196 | * @param jd 197 | * @return gmstSiderealHours 198 | */ 199 | @Deprecated 200 | public final double getGmstHours(final double jd) { 201 | final double julianCenturiesSinceJ2000 = getJulianCenturiesSinceJ2000(jd); 202 | final double h = 0D; 203 | final double gmstSiderealHours = 204 | GMST_HOUR_CONSTANT_1 205 | + (GMST_HOUR_CONSTANT_2 * julianCenturiesSinceJ2000) 206 | + (GMST_HOUR_CONSTANT_3 * h) 207 | - (GMST_HOUR_CONSTANT_4 * Math.pow(julianCenturiesSinceJ2000, 2)); 208 | return gmstSiderealHours; 209 | } 210 | 211 | /** 212 | * http://de.wikipedia.org/wiki/Sternzeit#Berechnung_der_Sternzeit 213 | * @param jd 214 | * @return sidereal time in degrees. 215 | */ 216 | public final double getSiderealDegrees(final double jd) { 217 | final double julianCenturiesSinceJ2000 = getJulianCenturiesSinceJ2000(jd); 218 | final double siderealDegrees = 219 | Constants.MEAN_LONGITUDE_OF_THE_SUN_PRECISE 220 | + (SIDEREAL_CONSTANT_1 * julianCenturiesSinceJ2000) 221 | + ((Math.pow(julianCenturiesSinceJ2000, 2)) / SIDEREAL_CONSTANT_2) 222 | - ((Math.pow(julianCenturiesSinceJ2000, 3)) / SIDEREAL_CONSTANT_3); 223 | return siderealDegrees; 224 | } 225 | 226 | /** 227 | * http://en.wikipedia.org/wiki/Sidereal_time#Definition 228 | * loss of precision of 0.1 second per century 229 | * @param decimalDays 230 | * @return sidereal time in hours 231 | */ 232 | public final double getSiderealHours(final double jd) { 233 | final double daysSinceJ2000 = jd - Constants.JULIAN_DAY_AT_01_01_2000; 234 | final double siderealHours = SIDEREAL_HOUR_CONSTANT_1 + (SIDEREAL_HOUR_CONSTANT_2 * daysSinceJ2000); 235 | return siderealHours; 236 | } 237 | 238 | /** 239 | * Converts asus into seconds compare: 240 | * http://www.aryabhatt.com/vediclessons/vediclesson5.htm 241 | * @param asus 242 | * @return 243 | */ 244 | public final long convertAsusToSiderealSeconds(final long asus) { 245 | return asus * 4L; 246 | } 247 | 248 | /** 249 | * http://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_Day_Number 250 | * @param date 251 | * @return 252 | */ 253 | public final double getJulianDayNumber(final Date date) { 254 | final String dateString = dateTimeFormat.format(date, TimeZone.createTimeZone(0)); 255 | final int dateYear = Integer.valueOf(dateString.substring(0, 4)); 256 | final int dateMonth = Integer.valueOf(dateString.substring(5, 7)); 257 | final int dateDay = Integer.valueOf(dateString.substring(8, 10)); 258 | final long a = ((MONTHS_PER_YEAR + 2L) - dateMonth) / MONTHS_PER_YEAR; 259 | final long y = dateYear + JULIAN_DAY_0_BC - a; 260 | final long m = dateMonth + (MONTHS_PER_YEAR * a) - 3; 261 | final double jdn = dateDay 262 | + (((MONTH_FACTOR * m) + 2L) / 5L) 263 | + (DAYS_PER_YEAR * y) 264 | + (y / LEAP_YEAR_CONSTANT_4) 265 | - (y / LEAP_YEAR_CONSTANT_100) 266 | + (y / LEAP_YEAR_CONSTANT_400) 267 | - JDN_OFFSET; 268 | return jdn; 269 | } 270 | 271 | public final double getJulianDayNumberWithTime(final Date date) { 272 | final double jdn = getJulianDayNumber(date); 273 | final String dateString = dateTimeFormat.format(date, TimeZone.createTimeZone(0)); 274 | final double hours = Double.valueOf(dateString.substring(11, 13)); 275 | final double minutes = Double.valueOf(dateString.substring(14, 16)); 276 | final double seconds = Double.valueOf(dateString.substring(17, 19)); 277 | final double result = jdn 278 | + ((hours - MONTHS_PER_YEAR) / Constants.HOURS_PER_DAY) 279 | + minutes / MINUTES_PER_DAY 280 | + seconds / SECONDS_PER_DAY; 281 | return result; 282 | } 283 | 284 | public final double getJulianDayNumberTimeDropped(final Date date) { 285 | final double jdn = getJulianDayNumber(date); 286 | final double hours = 0D; 287 | final double minutes = 0D; 288 | final double seconds = 0D; 289 | final double result = jdn 290 | + ((hours - MONTHS_PER_YEAR) / Constants.HOURS_PER_DAY) 291 | + minutes / MINUTES_PER_DAY 292 | + seconds / SECONDS_PER_DAY; 293 | return result; 294 | } 295 | 296 | /** 297 | * calculates julian centuries since J2000.0 for the provided julian day number 298 | * @param julianDayNumber 299 | * @return 300 | */ 301 | public final double getJulianCenturiesSinceJ2000(final double jd) { 302 | return ((jd - Constants.JULIAN_DAY_AT_01_01_2000) / DAYS_PER_JULIAN_CENTURY); //julian centuries since J2000 303 | } 304 | 305 | public final double calculateJulianDayNumberFromJd(final double julianDay) { 306 | return julianDay - Constants.JULIAN_DAY_AT_01_01_2000; // days since equinox J2000.0 307 | } 308 | 309 | /** 310 | * days since Jan 1, 2000 + 2451545 311 | * @param date 312 | * @return 313 | */ 314 | public final double calculateJulianDate(final Date date) { 315 | final long differenceMs = date.getTime() - new Date(MS_2000).getTime(); //milliseconds since 2000-01-01 00:00:00 316 | final double daysSince2000 = differenceMs / Double.valueOf(MS_PER_DAY); 317 | return Math.floor(daysSince2000 + Constants.JULIAN_DAY_AT_01_01_2000); 318 | } 319 | 320 | public final double calculateStarTimeHours(final double julianCenturies, final double decimalHours) { 321 | return STARTIME_CONSTANT_1 322 | + (STARTIME_CONSTANT_2 * julianCenturies) 323 | + (STARTIME_CONSTANT_3 * decimalHours); 324 | } 325 | 326 | public final double convertHoursToDegree(final double starTimeHours) { 327 | return starTimeHours * Constants.DEGREES_PER_HOUR; 328 | } 329 | 330 | public final double getDecimalHours(final Date date) { 331 | final String dateString = dateTimeFormat.format(date, TimeZone.createTimeZone(0)); 332 | final double hours = Double.valueOf(dateString.substring(11, 13)); 333 | final double minutes = Double.valueOf(dateString.substring(14, 16)); 334 | final double seconds = Double.valueOf(dateString.substring(17, 19)); 335 | final double decimalHours = hours + (minutes / Constants.SECONDS_PER_MINUTE) + (seconds / SECONDS_PER_HOUR); 336 | return decimalHours; 337 | } 338 | 339 | public final int getYear(final Date date) { 340 | return Integer.valueOf(dateTimeFormat.format(date).substring(DateTimeRange.Year.getFrom(), DateTimeRange.Year.getTo())); 341 | } 342 | 343 | public final int getMonth(final Date date) { 344 | return Integer.valueOf(dateTimeFormat.format(date).substring(DateTimeRange.Month.getFrom(), DateTimeRange.Month.getTo())); 345 | } 346 | 347 | public final int getDay(final Date date) { 348 | return Integer.valueOf(dateTimeFormat.format(date).substring(DateTimeRange.Days.getFrom(), DateTimeRange.Days.getTo())); 349 | } 350 | 351 | public final int getHours(final Date date) { 352 | return Integer.valueOf(dateTimeFormat.format(date).substring(DateTimeRange.Hours.getFrom(), DateTimeRange.Hours.getTo())); 353 | } 354 | 355 | public final int getMinutes(final Date date) { 356 | return Integer.valueOf(dateTimeFormat.format(date).substring(DateTimeRange.Minutes.getFrom(), DateTimeRange.Minutes.getTo())); 357 | } 358 | 359 | public final int getSeconds(final Date date) { 360 | return Integer.valueOf(dateTimeFormat.format(date).substring(DateTimeRange.Seconds.getFrom(), DateTimeRange.Seconds.getTo())); 361 | } 362 | 363 | public final double getLocalSiderealDegrees(final double siderealDegrees, final double longitude) { 364 | return clampResult((siderealDegrees % Constants.DEGREES_IN_CIRCLE) + longitude); 365 | } 366 | 367 | private double clampResult(final double result) { 368 | if (result < 0D) { 369 | return result + Constants.DEGREES_IN_CIRCLE; 370 | } else { 371 | return result; 372 | } 373 | } 374 | 375 | /** 376 | * http://en.wikipedia.org/wiki/Leap_year#Algorithm 377 | * @param year 378 | * @return 379 | */ 380 | public static final boolean isLeapYear(final int year) { 381 | if (year % LEAP_YEAR_CONSTANT_4 == 0) { 382 | if (year % LEAP_YEAR_CONSTANT_100 == 0) { 383 | return (year % LEAP_YEAR_CONSTANT_400 == 0); 384 | } else { 385 | return true; 386 | } 387 | } else { 388 | return false; 389 | } 390 | } 391 | 392 | } 393 | -------------------------------------------------------------------------------- /src/astrochart/client/view/AdminView.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.view; 2 | 3 | import astrochart.client.presenter.AdminPresenter; 4 | import com.google.gwt.user.client.ui.Button; 5 | import com.google.gwt.user.client.ui.Composite; 6 | import com.google.gwt.user.client.ui.DecoratorPanel; 7 | import com.google.gwt.user.client.ui.FlexTable; 8 | import com.google.gwt.user.client.ui.Label; 9 | import com.google.gwt.user.client.ui.TextArea; 10 | import com.google.gwt.user.client.ui.Widget; 11 | 12 | public class AdminView extends Composite implements AdminPresenter.Display { 13 | private final FlexTable contentTable; 14 | private final Button submitButton = new Button("Submit"); 15 | private final TextArea inputTextArea = new TextArea(); 16 | private final Label statusLabel = new Label(); 17 | private final Label secondStatusLabel = new Label(); 18 | 19 | public AdminView() { 20 | final DecoratorPanel contentTableDecorator = new DecoratorPanel(); 21 | contentTableDecorator.setWidth("1010px"); 22 | initWidget(contentTableDecorator); 23 | contentTable = new FlexTable(); 24 | contentTable.setWidget(0, 0, submitButton); 25 | inputTextArea.setWidth("997px"); 26 | inputTextArea.setHeight("500px"); 27 | contentTable.setWidget(1, 0, inputTextArea); 28 | contentTable.setWidget(2, 0, statusLabel); 29 | contentTable.setWidget(3, 0, secondStatusLabel); 30 | contentTableDecorator.add(contentTable); 31 | } 32 | 33 | @Override 34 | public final Widget asWidget() { 35 | return this; 36 | } 37 | 38 | @Override 39 | public final Button getSubmitButton() { 40 | return submitButton; 41 | } 42 | 43 | @Override 44 | public final TextArea getInputTextArea() { 45 | return inputTextArea; 46 | } 47 | 48 | @Override 49 | public final Label getStatusLabel() { 50 | return statusLabel; 51 | } 52 | 53 | @Override 54 | public final Label getSecondStatusLabel() { 55 | return secondStatusLabel; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/astrochart/client/view/ChartView.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.view; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import astrochart.client.presenter.ChartPresenter; 6 | import astrochart.client.util.DateTimeUtil; 7 | import astrochart.client.widgets.Chart; 8 | import astrochart.client.widgets.TimeEntry; 9 | import astrochart.shared.enums.AspectType; 10 | import astrochart.shared.enums.HouseType; 11 | import astrochart.shared.enums.Planet; 12 | import com.google.gwt.event.shared.HandlerManager; 13 | import com.google.gwt.user.client.ui.Button; 14 | import com.google.gwt.user.client.ui.CheckBox; 15 | import com.google.gwt.user.client.ui.Composite; 16 | import com.google.gwt.user.client.ui.DecoratorPanel; 17 | import com.google.gwt.user.client.ui.FlexTable; 18 | import com.google.gwt.user.client.ui.HTML; 19 | import com.google.gwt.user.client.ui.HasVerticalAlignment; 20 | import com.google.gwt.user.client.ui.HorizontalPanel; 21 | import com.google.gwt.user.client.ui.Label; 22 | import com.google.gwt.user.client.ui.ListBox; 23 | import com.google.gwt.user.client.ui.TextBox; 24 | import com.google.gwt.user.client.ui.VerticalPanel; 25 | import com.google.gwt.user.client.ui.Widget; 26 | 27 | public class ChartView extends Composite implements ChartPresenter.Display { 28 | private final FlexTable contentTable = new FlexTable(); 29 | private final Button updatePositionsButton = new Button("Update Positions"); 30 | private final Button regenerateChartButton = new Button("Regenerate Chart"); 31 | private final TextBox locationTextBox = new TextBox(); 32 | private final Button submitCityButton = new Button("Get"); 33 | private final Label latitudeLabel = new Label("Latitude: "); 34 | private final TextBox latitudeTextBox = new TextBox(); 35 | private final Button submitLatitudeButton = new Button("Set"); 36 | private final Label longitudeLabel = new Label("Longitude: "); 37 | private final TextBox longitudeTextBox = new TextBox(); 38 | private final Button submitLongitudeButton = new Button("Set"); 39 | private final Label utcLabel = new Label(); 40 | private final Label utcJdLabel = new Label(); 41 | private final Label utcSidLabel = new Label(); 42 | private final ListBox housesListBox = new ListBox(); 43 | private final Label sunriseLabel = new Label(); 44 | private final Label sunsetLabel = new Label(); 45 | private final Label sunPositionLabel = new Label(); 46 | private final Label ascendentLabel = new Label(); 47 | private final Label statusLabel = new Label(); 48 | private final Map planetCheckBoxes = new HashMap(); 49 | private final Map planetLabels = new HashMap(); 50 | private final Button selectAllPlanetsButton = new Button("Select All"); 51 | private final Button unselectAllPlanetsButton = new Button("Unselect All"); 52 | private final Map aspectCheckBoxes = new HashMap(); 53 | private final Map aspectLabels = new HashMap(); 54 | private final Map aspectListboxes = new HashMap(); 55 | private final Button selectAllAspectsButton = new Button("Select All"); 56 | private final Button unselectAllAspectsButton = new Button("Unselect All"); 57 | private final Button resetOrbsButton = new Button("Reset Orbs"); 58 | 59 | private final TimeEntry timeEntry; 60 | private final Chart chart; 61 | private int row; 62 | 63 | public ChartView(final HandlerManager eventBus, final DateTimeUtil dateTimeUtil) { 64 | final DecoratorPanel contentTableDecorator = new DecoratorPanel(); 65 | contentTableDecorator.setWidth("1010px"); 66 | initWidget(contentTableDecorator); 67 | 68 | row = 0; 69 | final HorizontalPanel buttonPanel = new HorizontalPanel(); 70 | buttonPanel.setSpacing(5); 71 | buttonPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); 72 | 73 | final HorizontalPanel locPanel = new HorizontalPanel(); 74 | locPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); 75 | locationTextBox.setText("unknown"); 76 | locationTextBox.setWidth("240px"); 77 | locPanel.add(new Label("Location: ")); 78 | locPanel.add(locationTextBox); 79 | locPanel.add(submitCityButton); 80 | buttonPanel.add(locPanel); 81 | 82 | final HorizontalPanel latPanel = new HorizontalPanel(); 83 | latPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); 84 | latitudeTextBox.setText("0.0000000"); 85 | latitudeTextBox.setWidth("80px"); 86 | latPanel.add(latitudeLabel); 87 | latPanel.add(latitudeTextBox); 88 | latPanel.add(submitLatitudeButton); 89 | buttonPanel.add(latPanel); 90 | 91 | final HorizontalPanel longPanel = new HorizontalPanel(); 92 | longPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); 93 | longitudeTextBox.setText("0.0000000"); 94 | longitudeTextBox.setWidth("80px"); 95 | longPanel.add(longitudeLabel); 96 | longPanel.add(longitudeTextBox); 97 | longPanel.add(submitLongitudeButton); 98 | buttonPanel.add(longPanel); 99 | buttonPanel.add(updatePositionsButton); 100 | buttonPanel.add(regenerateChartButton); 101 | contentTable.setWidget(row, 0, buttonPanel); 102 | contentTable.getFlexCellFormatter().setColSpan(row, 0, 3); 103 | row++; 104 | 105 | timeEntry = new TimeEntry(eventBus, dateTimeUtil); 106 | final VerticalPanel chartPanel = new VerticalPanel(); 107 | chartPanel.add(timeEntry); 108 | chart = new Chart(eventBus, planetCheckBoxes, aspectListboxes, aspectCheckBoxes, aspectLabels); 109 | chartPanel.add(chart); 110 | 111 | contentTable.setWidget(row, 0, chartPanel); 112 | contentTable.setText(row, 1, "UTC Time: "); 113 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_MIDDLE); 114 | contentTable.setWidget(row, 2, utcLabel); 115 | contentTable.getCellFormatter().setVerticalAlignment(row, 1, HasVerticalAlignment.ALIGN_MIDDLE); 116 | row++; 117 | 118 | addRow("UTC JD Time: ", utcJdLabel); 119 | addRow("UTC Sidereal Time: ", utcSidLabel); 120 | contentTable.setWidget(row, 0, new HTML(" ")); 121 | row++; 122 | 123 | for (final Planet planet : Planet.values()) { 124 | final HorizontalPanel pan = new HorizontalPanel(); 125 | final CheckBox planetCheckBox = new CheckBox(); 126 | if (planet.isBody() && !planet.isOuter()) { 127 | planetCheckBox.setValue(true); 128 | } 129 | planetCheckBoxes.put(planet, planetCheckBox); 130 | final Label planetLabel = new Label(); 131 | planetLabels.put(planet, planetLabel); 132 | pan.add(planetCheckBox); 133 | pan.add(new Label(planet.getUnicode() + " " + planet.name() + ": ")); 134 | addWidgetRow(pan, planetLabel); 135 | } 136 | 137 | final HorizontalPanel planetButtonPan = new HorizontalPanel(); 138 | planetButtonPan.add(selectAllPlanetsButton); 139 | planetButtonPan.add(unselectAllPlanetsButton); 140 | contentTable.setWidget(row, 0, planetButtonPan); 141 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP); 142 | contentTable.getFlexCellFormatter().setColSpan(row, 0, 2); 143 | row++; 144 | 145 | contentTable.setWidget(row, 0, new HTML(" ")); 146 | row++; 147 | 148 | for (final HouseType houseType : HouseType.values()) { 149 | housesListBox.addItem(houseType.getName()); 150 | } 151 | contentTable.setText(row, 0, "Houses System: "); 152 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_MIDDLE); 153 | contentTable.setWidget(row, 1, housesListBox); 154 | contentTable.getCellFormatter().setVerticalAlignment(row, 1, HasVerticalAlignment.ALIGN_MIDDLE); 155 | row++; 156 | 157 | contentTable.setWidget(row, 0, new HTML(" ")); 158 | row++; 159 | 160 | final FlexTable aspectFlex = new FlexTable(); 161 | aspectFlex.setText(0, 0, "Aspect"); 162 | aspectFlex.setText(0, 1, "Counter"); 163 | aspectFlex.setText(0, 2, "Orb"); 164 | int aspectRow = 1; 165 | for (final AspectType aspectType : AspectType.values()) { 166 | final HorizontalPanel pan = new HorizontalPanel(); 167 | final CheckBox aspectCheckBox = new CheckBox(); 168 | aspectCheckBox.setValue(true); 169 | aspectCheckBoxes.put(aspectType, aspectCheckBox); 170 | pan.add(aspectCheckBox); 171 | pan.add(new Label(aspectType.getUnicode() + " " + aspectType.name() + "s: ")); 172 | aspectFlex.setWidget(aspectRow, 0, pan); 173 | final Label aspectLabel = new Label(); 174 | aspectLabel.setText("0"); 175 | aspectLabels.put(aspectType, aspectLabel); 176 | aspectFlex.setWidget(aspectRow, 1, aspectLabel); 177 | final ListBox listBox = new ListBox(); 178 | listBox.setWidth("70px"); 179 | for (final double orb : aspectType.getOrbs()) { 180 | listBox.addItem(String.valueOf(orb)); 181 | } 182 | aspectListboxes.put(aspectType, listBox); 183 | aspectFlex.setWidget(aspectRow, 2, listBox); 184 | aspectRow++; 185 | } 186 | resetOrbs(); 187 | contentTable.setWidget(row, 0, aspectFlex); 188 | contentTable.getFlexCellFormatter().setColSpan(row, 0, 2); 189 | row++; 190 | 191 | final HorizontalPanel aspectButtonPan = new HorizontalPanel(); 192 | aspectButtonPan.add(selectAllAspectsButton); 193 | aspectButtonPan.add(unselectAllAspectsButton); 194 | aspectButtonPan.add(resetOrbsButton); 195 | contentTable.setWidget(row, 0, aspectButtonPan); 196 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP); 197 | contentTable.getFlexCellFormatter().setColSpan(row, 0, 2); 198 | row++; 199 | 200 | contentTable.setWidget(row, 0, new HTML(" ")); 201 | row++; 202 | 203 | addRow("Sunrise Time: ", sunriseLabel); 204 | addRow("Sunset Time: ", sunsetLabel); 205 | addRow("Sun Position: ", sunPositionLabel); 206 | addRow("Tropical Ascendent: ", ascendentLabel); 207 | contentTable.setWidget(row, 0, statusLabel); 208 | contentTable.getFlexCellFormatter().setColSpan(row, 0, 3); 209 | contentTable.getFlexCellFormatter().setRowSpan(1, 0, row - 1); // chart 210 | contentTableDecorator.add(contentTable); 211 | } 212 | 213 | private void addRow(final String label, final Widget widget) { 214 | contentTable.setText(row, 0, label); 215 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP); 216 | contentTable.setWidget(row, 1, widget); 217 | contentTable.getCellFormatter().setVerticalAlignment(row, 1, HasVerticalAlignment.ALIGN_TOP); 218 | row++; 219 | } 220 | 221 | private void addWidgetRow(final Widget first, final Widget second) { 222 | contentTable.setWidget(row, 0, first); 223 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP); 224 | contentTable.setWidget(row, 1, second); 225 | contentTable.getCellFormatter().setVerticalAlignment(row, 1, HasVerticalAlignment.ALIGN_TOP); 226 | row++; 227 | } 228 | 229 | @SuppressWarnings("unused") 230 | private void addRow(final String label, final Widget firstWidget, final Widget secondWidget) { 231 | contentTable.setText(row, 0, label); 232 | contentTable.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP); 233 | contentTable.setWidget(row, 1, firstWidget); 234 | contentTable.getCellFormatter().setVerticalAlignment(row, 1, HasVerticalAlignment.ALIGN_TOP); 235 | contentTable.setWidget(row, 2, secondWidget); 236 | contentTable.getCellFormatter().setVerticalAlignment(row, 2, HasVerticalAlignment.ALIGN_TOP); 237 | row++; 238 | } 239 | 240 | @Override 241 | public final Widget asWidget() { 242 | return this; 243 | } 244 | 245 | @Override 246 | public final Button getUpdatePositionsButton() { 247 | return updatePositionsButton; 248 | } 249 | 250 | @Override 251 | public final Button getRegenerateChartButton() { 252 | return regenerateChartButton; 253 | } 254 | 255 | @Override 256 | public final Label getUtcLabel() { 257 | return utcLabel; 258 | } 259 | 260 | @Override 261 | public final Label getUtcJdLabel() { 262 | return utcJdLabel; 263 | } 264 | 265 | @Override 266 | public final Label getUtcSidLabel() { 267 | return utcSidLabel; 268 | } 269 | 270 | @Override 271 | public final Chart getChart() { 272 | return chart; 273 | } 274 | 275 | @Override 276 | public final CheckBox getPlanetCheckBox(final Planet planet) { 277 | return planetCheckBoxes.get(planet); 278 | } 279 | 280 | @Override 281 | public final Label getPlanetLabel(final Planet planet) { 282 | return planetLabels.get(planet); 283 | } 284 | 285 | @Override 286 | public final Button getSelectAllPlanetsButton() { 287 | return selectAllPlanetsButton; 288 | } 289 | 290 | @Override 291 | public final Button getUnselectAllPlanetsButton() { 292 | return unselectAllPlanetsButton; 293 | } 294 | 295 | @Override 296 | public final ListBox getHousesListBox() { 297 | return housesListBox; 298 | } 299 | 300 | @Override 301 | public final CheckBox getAspectCheckBox(final AspectType type) { 302 | return aspectCheckBoxes.get(type); 303 | } 304 | 305 | @Override 306 | public final ListBox getAspectListBox(final AspectType type) { 307 | return aspectListboxes.get(type); 308 | } 309 | 310 | @Override 311 | public final Label getAspectLabel(final AspectType type) { 312 | return aspectLabels.get(type); 313 | } 314 | 315 | @Override 316 | public final void resetAspects() { 317 | for (final AspectType aspectType : AspectType.values()) { 318 | getAspectLabel(aspectType).setText("0"); 319 | } 320 | } 321 | 322 | @Override 323 | public final Button resetOrbsButton() { 324 | return resetOrbsButton; 325 | } 326 | 327 | @Override 328 | public final Button getUnselectAllAspectsButton() { 329 | return unselectAllAspectsButton; 330 | } 331 | 332 | @Override 333 | public final Button getSelectAllAspectsButton() { 334 | return selectAllAspectsButton; 335 | } 336 | 337 | @Override 338 | public final void resetOrbs() { 339 | for (final AspectType aspectType : AspectType.values()) { 340 | int index = 0; 341 | for (final double orb : aspectType.getOrbs()) { 342 | if (orb == aspectType.getDefaultOrb()) { 343 | getAspectListBox(aspectType).setItemSelected(index, true); 344 | } 345 | index++; 346 | } 347 | } 348 | } 349 | 350 | @Override 351 | public final TextBox getLocationTextBox() { 352 | return locationTextBox; 353 | } 354 | 355 | @Override 356 | public final Button getSubmitCityButton() { 357 | return submitCityButton; 358 | } 359 | 360 | @Override 361 | public final TextBox getLatitudeTextBox() { 362 | return latitudeTextBox; 363 | } 364 | 365 | @Override 366 | public final Button getSubmitLatitudeButton() { 367 | return submitLatitudeButton; 368 | } 369 | 370 | @Override 371 | public final TextBox getLongitudeTextBox() { 372 | return longitudeTextBox; 373 | } 374 | 375 | @Override 376 | public final Button getSubmitLongitudeButton() { 377 | return submitLongitudeButton; 378 | } 379 | 380 | @Override 381 | public final Label getSunriseLabel() { 382 | return sunriseLabel; 383 | } 384 | 385 | @Override 386 | public final Label getSunsetLabel() { 387 | return sunsetLabel; 388 | } 389 | 390 | @Override 391 | public final Label getSunPositionLabel() { 392 | return sunPositionLabel; 393 | } 394 | 395 | @Override 396 | public final Label getAscendentLabel() { 397 | return ascendentLabel; 398 | } 399 | 400 | @Override 401 | public final Label getStatusLabel() { 402 | return statusLabel; 403 | } 404 | 405 | @Override 406 | public final TimeEntry getTimeEntry() { 407 | return timeEntry; 408 | } 409 | } 410 | -------------------------------------------------------------------------------- /src/astrochart/client/view/InfoView.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.view; 2 | 3 | import astrochart.client.presenter.InfoPresenter; 4 | 5 | import com.google.gwt.user.client.ui.Composite; 6 | import com.google.gwt.user.client.ui.DecoratorPanel; 7 | import com.google.gwt.user.client.ui.FlexTable; 8 | import com.google.gwt.user.client.ui.Widget; 9 | 10 | public class InfoView extends Composite implements InfoPresenter.Display { 11 | private final FlexTable contentTable; 12 | private final FlexTable infoList = new FlexTable(); 13 | 14 | public InfoView() { 15 | final DecoratorPanel contentTableDecorator = new DecoratorPanel(); 16 | contentTableDecorator.setWidth("1010px"); 17 | initWidget(contentTableDecorator); 18 | contentTable = new FlexTable(); 19 | infoList.setWidth("987px"); 20 | contentTable.setWidget(0, 0, infoList); 21 | contentTableDecorator.add(contentTable); 22 | } 23 | 24 | @Override 25 | public final Widget asWidget() { 26 | return this; 27 | } 28 | 29 | @Override 30 | public final FlexTable getInfoList() { 31 | return infoList; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/astrochart/client/widgets/Chart.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.widgets; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | import astrochart.client.event.ResetAspectsEvent; 8 | import astrochart.client.event.SetStatusEvent; 9 | import astrochart.shared.data.Epoch; 10 | import astrochart.shared.enums.AspectType; 11 | import astrochart.shared.enums.ChartColor; 12 | import astrochart.shared.enums.ChartProportions; 13 | import astrochart.shared.enums.HouseType; 14 | import astrochart.shared.enums.Planet; 15 | import astrochart.shared.enums.ZodiacSign; 16 | import astrochart.shared.wrappers.AscendentAndOffset; 17 | import astrochart.shared.wrappers.TextPosition; 18 | import com.google.gwt.canvas.client.Canvas; 19 | import com.google.gwt.canvas.dom.client.Context2d; 20 | import com.google.gwt.canvas.dom.client.CssColor; 21 | import com.google.gwt.core.client.Scheduler; 22 | import com.google.gwt.core.client.Scheduler.ScheduledCommand; 23 | import com.google.gwt.event.shared.HandlerManager; 24 | import com.google.gwt.user.client.ui.CheckBox; 25 | import com.google.gwt.user.client.ui.Composite; 26 | import com.google.gwt.user.client.ui.Label; 27 | import com.google.gwt.user.client.ui.ListBox; 28 | import com.google.gwt.user.client.ui.VerticalPanel; 29 | 30 | public class Chart extends Composite { 31 | private static final int CANVAS_WIDTH = 600; 32 | private static final int CANVAS_HEIGHT = 600; 33 | private static final int TEXT_SIZE_LARGER = 12; 34 | private static final int TEXT_SIZE_LARGE = 8; 35 | private static final double LINE_WIDTH_LIGHT = 0.8; 36 | private static final double LINE_WIDTH_LIGHTER = 0.75D; 37 | private static final double LINE_WIDTH_ALMOSTSUPERLIGHT = 0.40; 38 | private static final double LINE_WIDTH_SUPERLIGHT = 0.20; 39 | private static final double LINE_WIDTH_HYPERLIGHT = 0.10; 40 | private static final int Y_OFFSET = 18; 41 | private static final int X_OFFSET = 23; 42 | private static final double FULL_CIRCLE = 360D; 43 | private static final double RIGHT_ANGLE = 90D; 44 | private static final double DEGREES_PER_SIGN = 30D; 45 | private static final double DEGREES_PER_HALF_SIGN = DEGREES_PER_SIGN / 2; 46 | private final HandlerManager eventBus; 47 | private final Map planetCheckBoxes; 48 | private final Map aspectListboxes; 49 | private final Map aspectCheckBoxes; 50 | private final Map aspectLabels; 51 | private final VerticalPanel chartPanel = new VerticalPanel(); 52 | private final Canvas canvas = Canvas.createIfSupported(); 53 | private AscendentAndOffset ascendent; 54 | private Epoch epoch; 55 | @SuppressWarnings("unused") 56 | private HouseType houseType; 57 | private final Map aspects = new HashMap(); 58 | 59 | public Chart(final HandlerManager eventBus, final Map planetCheckBoxes, final Map aspectListboxes, 60 | final Map aspectCheckBoxes, final Map aspectLabels) { 61 | this.eventBus = eventBus; 62 | this.planetCheckBoxes = planetCheckBoxes; 63 | this.aspectListboxes = aspectListboxes; 64 | this.aspectCheckBoxes = aspectCheckBoxes; 65 | this.aspectLabels = aspectLabels; 66 | if (canvas != null) { 67 | canvas.setCoordinateSpaceWidth(CANVAS_WIDTH); 68 | canvas.setCoordinateSpaceHeight(CANVAS_HEIGHT); 69 | chartPanel.add(canvas); 70 | } else { 71 | chartPanel.add(new Label("Fail: Your browser doesn't support HTML5 Canvas.")); 72 | } 73 | initWidget(chartPanel); 74 | setStyleName("chart"); 75 | } 76 | 77 | @SuppressWarnings("unused") 78 | private void generateEmptyChart() { 79 | Scheduler.get().scheduleDeferred(new ScheduledCommand() { 80 | @Override 81 | public void execute() { 82 | generateChart(new AscendentAndOffset(ZodiacSign.Aries, 0.0D, ((FULL_CIRCLE * 3) / 4)), null, HouseType.Equal); 83 | } 84 | }); 85 | } 86 | 87 | public final void generateChart(final AscendentAndOffset ascendent, final Epoch epoch, final HouseType houseType) { 88 | this.ascendent = ascendent; 89 | this.epoch = epoch; 90 | this.houseType = houseType; 91 | final Context2d ctx = canvas.getContext2d(); 92 | ctx.setStrokeStyle(CssColor.make(ChartColor.Black.getHex())); 93 | ctx.setFillStyle(CssColor.make(ChartColor.White.getHex())); 94 | ctx.setFont("10pt Arial"); 95 | ctx.fillRect(0, 0, canvas.getOffsetWidth(), canvas.getOffsetHeight()); //clear ctx 96 | 97 | final double offset = ascendent.getOffset() + ascendent.getAscendent().getEclipticLongitude(); 98 | 99 | ctx.setLineWidth(1D); 100 | markFiveDegrees(ctx, offset); 101 | markDegrees(ctx, offset); 102 | drawAscendentLine( 103 | getXCenter(), 104 | getYCenter(), 105 | ChartProportions.getRadius(getHcs(), ChartProportions.Inner), 106 | ascendent); 107 | 108 | ctx.setLineWidth(2D); 109 | drawArc(getXCenter(), 110 | getYCenter(), 111 | ChartProportions.getRadius(getHcs(), ChartProportions.Inner), 112 | 0D, 113 | FULL_CIRCLE, 114 | false); 115 | 116 | //put zodiac 117 | ctx.setFont("36pt Arial"); 118 | for (final ZodiacSign sign : ZodiacSign.values()) { 119 | final double angle = keepInRange(sign.getEclipticLongitude() + RIGHT_ANGLE - offset); 120 | 121 | //draw colored section 122 | ctx.beginPath(); 123 | ctx.setFillStyle(CssColor.make(sign.getColor().getHex())); 124 | final double start = Math.toRadians((sign.getEclipticLongitude() * -1) + (FULL_CIRCLE / 2) - DEGREES_PER_SIGN + offset); 125 | final double end = Math.toRadians((sign.getEclipticLongitude() * -1) + (FULL_CIRCLE / 2) + offset); 126 | ctx.arc(getXCenter(), getYCenter(), ChartProportions.getRadius(getHcs(), ChartProportions.OuterEclyptic), start, end, false); 127 | ctx.arc(getXCenter(), getYCenter(), ChartProportions.getRadius(getHcs(), ChartProportions.InnerEclyptic), end, start, true); 128 | ctx.fill(); 129 | ctx.stroke(); 130 | ctx.closePath(); 131 | 132 | //draw Signs 133 | final double xSign = getHcs() 134 | - (Math.sin(Math.toRadians(angle + DEGREES_PER_HALF_SIGN)) 135 | * ChartProportions.getRadius(getHcs(), ChartProportions.EclypticCenter)) - X_OFFSET; 136 | final double ySign = getHcs() 137 | - (Math.cos(Math.toRadians(angle + DEGREES_PER_HALF_SIGN)) 138 | * ChartProportions.getRadius(getHcs(), ChartProportions.EclypticCenter)) + Y_OFFSET; 139 | ctx.beginPath(); 140 | ctx.setFillStyle(CssColor.make(ChartColor.White.getHex())); 141 | ctx.setStrokeStyle(CssColor.make(ChartColor.Black.getHex())); 142 | ctx.fillText(String.valueOf(sign.getUnicode()), xSign, ySign); 143 | ctx.strokeText(String.valueOf(sign.getUnicode()), xSign, ySign); 144 | ctx.closePath(); 145 | } 146 | 147 | //draw houses 148 | int house = 1; 149 | if (houseType.equals(HouseType.Equal) || houseType.equals(HouseType.WholeSigns)) { 150 | for (final ZodiacSign sign : ZodiacSign.values()) { 151 | double angle = keepInRange(sign.getEclipticLongitude() + RIGHT_ANGLE); 152 | if (houseType.equals(HouseType.WholeSigns)) { 153 | angle = angle - (offset % DEGREES_PER_SIGN); 154 | } 155 | ctx.setLineWidth(LINE_WIDTH_HYPERLIGHT); 156 | drawExcentricLine(ctx, angle, ChartProportions.Inner, ChartProportions.InnerMark); 157 | drawExcentricLine(ctx, angle, ChartProportions.OuterEclyptic, ChartProportions.Outer); 158 | ctx.setLineWidth(LINE_WIDTH_LIGHT); 159 | writeExcentricInfo(ctx, TEXT_SIZE_LARGE, String.valueOf(house), angle + DEGREES_PER_HALF_SIGN, ChartProportions.HouseNumber); 160 | house++; 161 | } 162 | } 163 | 164 | if (epoch != null) { 165 | //place planet information 166 | ctx.setLineWidth(LINE_WIDTH_LIGHTER); 167 | for (final Planet planet : Planet.values()) { 168 | if (planetCheckBoxes.get(planet).getValue()) { 169 | final ZodiacSign sign = ZodiacSign.valueOfAbbrevistion(epoch.getSign(planet)); 170 | final double degrees = epoch.getPreciseDegrees(planet) + sign.getEclipticLongitude(); 171 | final double angle = keepInRange(degrees + RIGHT_ANGLE - Double.valueOf(offset).intValue()); 172 | drawExcentricLine(ctx, angle, ChartProportions.PlanetMark, ChartProportions.InnerMark); //draw outer planet mark 173 | writeExcentricInfo(ctx, TEXT_SIZE_LARGER, String.valueOf(planet.getUnicode()), angle, ChartProportions.PlanetSign); 174 | writeExcentricInfo(ctx, TEXT_SIZE_LARGE, epoch.getDegrees(planet) + String.valueOf('\u00B0'), angle, ChartProportions.Degree); 175 | writeExcentricInfo(ctx, TEXT_SIZE_LARGE, epoch.getMinutes(planet) + String.valueOf('\u2032'), angle, ChartProportions.Minute); 176 | drawExcentricLine(ctx, angle, ChartProportions.Inner, ChartProportions.InnerLine); //draw inner planet mark 177 | } 178 | } 179 | 180 | /* 181 | //mark midheaven 182 | System.out.println("MC: " + ascendent.getMidheaven()); 183 | final double angle = keepInRange(ascendent.getMidheaven()); 184 | drawExcentricLine(ctx, angle, ChartProportions.PlanetMark, ChartProportions.InnerMark); //draw outer mark 185 | writeExcentricInfo(ctx, 12, "MC", angle, ChartProportions.PlanetSign); 186 | drawExcentricLine(ctx, angle, ChartProportions.Degree, ChartProportions.Inner); //draw inner mark 187 | */ 188 | 189 | //draw aspects 190 | eventBus.fireEvent(new ResetAspectsEvent()); 191 | aspects.clear(); 192 | for (final Planet firstPlanet : Planet.values()) { 193 | if (planetCheckBoxes.get(firstPlanet).getValue()) { 194 | for (final Planet secondPlanet : Planet.values()) { 195 | if (planetCheckBoxes.get(secondPlanet).getValue()) { 196 | drawAspectLine(ctx, firstPlanet, secondPlanet, offset); 197 | } 198 | } 199 | } 200 | } 201 | 202 | //write aspect labels 203 | ctx.setFont("12pt Arial"); 204 | final Iterator> it = aspects.entrySet().iterator(); 205 | while (it.hasNext()) { 206 | final Entry entry = it.next(); 207 | if (entry.getValue() != null) { 208 | final TextPosition tp = entry.getValue(); 209 | ctx.setLineWidth(LINE_WIDTH_ALMOSTSUPERLIGHT); 210 | ctx.fillRect(tp.getX() - 1D, tp.getY() - DEGREES_PER_HALF_SIGN - 3, DEGREES_PER_HALF_SIGN - 1, DEGREES_PER_HALF_SIGN); 211 | ctx.strokeRect(tp.getX() - 1D, tp.getY() - DEGREES_PER_HALF_SIGN - 3, DEGREES_PER_HALF_SIGN - 1, DEGREES_PER_HALF_SIGN); 212 | ctx.setLineWidth(1D); 213 | ctx.strokeText(tp.getText(), tp.getX(), tp.getY()); 214 | it.remove(); // avoids a ConcurrentModificationException 215 | } 216 | } 217 | } 218 | eventBus.fireEvent(new SetStatusEvent("Ready.")); 219 | } 220 | 221 | private void drawAspectLine(final Context2d ctx, final Planet firstPlanet, final Planet secondPlanet, final double offset) { 222 | if (firstPlanet.equals(secondPlanet) 223 | || aspects.containsKey(secondPlanet.name() + ":" + firstPlanet.name())) { 224 | return; //aspect already placed 225 | } 226 | 227 | final ZodiacSign firstSign = ZodiacSign.valueOfAbbrevistion(epoch.getSign(firstPlanet)); 228 | final double firstDegrees = epoch.getPreciseDegrees(firstPlanet) + firstSign.getEclipticLongitude(); 229 | final double firstAngle = keepInRange(firstDegrees + RIGHT_ANGLE - Double.valueOf(offset).intValue()); 230 | final ZodiacSign secondSign = ZodiacSign.valueOfAbbrevistion(epoch.getSign(secondPlanet)); 231 | final double secondDegrees = epoch.getPreciseDegrees(secondPlanet) + secondSign.getEclipticLongitude(); 232 | final double secondAngle = keepInRange(secondDegrees + RIGHT_ANGLE - Double.valueOf(offset).intValue()); 233 | 234 | final double xFirst = getHcs() 235 | - (Math.sin(Math.toRadians(firstAngle)) * ChartProportions.getRadius(getHcs(), ChartProportions.Inner)); 236 | final double yFirst = getHcs() 237 | - (Math.cos(Math.toRadians(firstAngle)) * ChartProportions.getRadius(getHcs(), ChartProportions.Inner)); 238 | final double xSecond = getHcs() 239 | - (Math.sin(Math.toRadians(secondAngle)) * ChartProportions.getRadius(getHcs(), ChartProportions.Inner)); 240 | final double ySecond = getHcs() 241 | - (Math.cos(Math.toRadians(secondAngle)) * ChartProportions.getRadius(getHcs(), ChartProportions.Inner)); 242 | 243 | double difference = firstAngle - secondAngle; 244 | if (difference < 0D) { 245 | difference = difference * -1D; 246 | } 247 | AspectType isType = null; 248 | for (final AspectType type : AspectType.values()) { 249 | if (difference <= type.getAngle() + getAspectOrb(type) 250 | && difference >= type.getAngle() - getAspectOrb(type)) { 251 | isType = type; 252 | break; 253 | } 254 | } 255 | TextPosition tp = null; 256 | if (isType != null) { 257 | addAspect(isType); 258 | if (aspectCheckBoxes.get(isType).getValue()) { 259 | ctx.setLineWidth(2.0D); //Labeled aspects with type 260 | drawLine(xFirst, yFirst, xSecond, ySecond); 261 | final double x = ((xFirst + xSecond) / 2D) - 6D; 262 | final double y = ((yFirst + ySecond) / 2D) + 6D; 263 | tp = new TextPosition(String.valueOf(isType.getUnicode()), x, y); 264 | } else { 265 | ctx.setLineWidth(1.0D); //Unlabeled Aspects with type 266 | drawLine(xFirst, yFirst, xSecond, ySecond); 267 | } 268 | } else { 269 | ctx.setLineWidth(LINE_WIDTH_SUPERLIGHT); //Apsects without type 270 | drawLine(xFirst, yFirst, xSecond, ySecond); 271 | } 272 | aspects.put(firstPlanet.name() + ":" + secondPlanet.name(), tp); 273 | } 274 | 275 | private void drawExcentricLine(final Context2d ctx, final double angle, final ChartProportions from, final ChartProportions to) { 276 | final double xFrom = getHcs() - (Math.sin(Math.toRadians(angle)) * ChartProportions.getRadius(getHcs(), from)); 277 | final double yFrom = getHcs() - (Math.cos(Math.toRadians(angle)) * ChartProportions.getRadius(getHcs(), from)); 278 | final double xTo = getHcs() - (Math.sin(Math.toRadians(angle)) * ChartProportions.getRadius(getHcs(), to)); 279 | final double yTo = getHcs() - (Math.cos(Math.toRadians(angle)) * ChartProportions.getRadius(getHcs(), to)); 280 | drawLine(xFrom, yFrom, xTo, yTo); 281 | } 282 | 283 | private void writeExcentricInfo(final Context2d ctx, final int textSize, final String text, final double angle, final ChartProportions prop) { 284 | ctx.setFont(textSize + "pt Arial"); 285 | final double xMinute = getHcs() - (Math.sin(Math.toRadians(angle)) * ChartProportions.getRadius(getHcs(), prop)) - (textSize / 2); 286 | final double yMinute = getHcs() - (Math.cos(Math.toRadians(angle)) * ChartProportions.getRadius(getHcs(), prop)) + (textSize / 2); 287 | ctx.strokeText(text, xMinute, yMinute); 288 | } 289 | 290 | private void markFiveDegrees(final Context2d ctx, final double offset) { 291 | for (int angle = 0; angle < FULL_CIRCLE; angle = angle + 5) { 292 | ctx.beginPath(); 293 | ctx.setFillStyle(CssColor.make(ChartColor.White.getHex())); 294 | ctx.setStrokeStyle(CssColor.make(ChartColor.Black.getHex())); 295 | final double start = Math.toRadians(angle + offset); 296 | final double end = Math.toRadians(angle + offset + 5D); 297 | ctx.arc(getXCenter(), getYCenter(), ChartProportions.getRadius(getHcs(), ChartProportions.InnerEclyptic), start, end, false); 298 | ctx.arc(getXCenter(), getYCenter(), ChartProportions.getRadius(getHcs(), ChartProportions.OuterMark), end, start, true); 299 | ctx.fill(); 300 | ctx.stroke(); 301 | ctx.closePath(); 302 | } 303 | } 304 | 305 | private void markDegrees(final Context2d ctx, final double offset) { 306 | for (int angle = 0; angle < FULL_CIRCLE; angle++) { 307 | ctx.beginPath(); 308 | ctx.setFillStyle(CssColor.make(ChartColor.White.getHex())); 309 | ctx.setStrokeStyle(CssColor.make(ChartColor.Black.getHex())); 310 | final double start = Math.toRadians(angle + offset); 311 | final double end = Math.toRadians(angle + offset + 1D); 312 | ctx.arc(getXCenter(), getYCenter(), ChartProportions.getRadius(getHcs(), ChartProportions.OuterMark), start, end, false); 313 | ctx.arc(getXCenter(), getYCenter(), ChartProportions.getRadius(getHcs(), ChartProportions.InnerMark), end, start, true); 314 | ctx.fill(); 315 | ctx.stroke(); 316 | ctx.closePath(); 317 | } 318 | } 319 | 320 | /** 321 | * returns the half size of the chart 322 | * @return 323 | */ 324 | private int getHcs() { 325 | if (getXCenter() >= getYCenter()) { 326 | return getXCenter(); 327 | } else { 328 | return getYCenter(); 329 | } 330 | } 331 | 332 | private int getXCenter() { 333 | return canvas.getOffsetWidth() / 2; 334 | } 335 | 336 | private int getYCenter() { 337 | return canvas.getOffsetHeight() / 2; 338 | } 339 | 340 | private double keepInRange(final double angle) { 341 | double result = angle; 342 | while (result < 0D) { 343 | result = result + FULL_CIRCLE; 344 | } 345 | result = result % FULL_CIRCLE; 346 | return result; 347 | } 348 | 349 | private void drawArc(final int x, final int y, final int r, 350 | final double startAngle, final double endAngle, final boolean antiClock) { 351 | canvas.getContext2d().beginPath(); 352 | final double start = Math.toRadians(startAngle - RIGHT_ANGLE); 353 | final double end = Math.toRadians(endAngle - RIGHT_ANGLE); 354 | canvas.getContext2d().arc(x, y, r, start, end, antiClock); 355 | canvas.getContext2d().fill(); 356 | canvas.getContext2d().stroke(); 357 | canvas.getContext2d().closePath(); 358 | } 359 | 360 | private void drawAscendentLine(final int xCenter, final int yCenter, final int innerRadius, 361 | final AscendentAndOffset asc) { 362 | drawLine(xCenter - ChartProportions.getRadius(getHcs(), ChartProportions.Inner), yCenter, 363 | xCenter - ChartProportions.getRadius(getHcs(), ChartProportions.InnerMark), yCenter); 364 | final String text = "ASC " + asc.getAscendent().getUnicode() + " " + asc.getFormattedOffset(); 365 | canvas.getContext2d().strokeText(text, xCenter - ChartProportions.getRadius(getHcs(), ChartProportions.InnerMark) + 5D, yCenter - 5D); 366 | } 367 | 368 | private void drawLine(final double startX, final double startY, final double endX, final double endY) { 369 | canvas.getContext2d().beginPath(); 370 | canvas.getContext2d().moveTo(startX, startY); 371 | canvas.getContext2d().lineTo(endX, endY); 372 | canvas.getContext2d().closePath(); 373 | canvas.getContext2d().stroke(); 374 | } 375 | 376 | private double getAspectOrb(final AspectType type) { 377 | final ListBox box = aspectListboxes.get(type); 378 | final int selection = box.getSelectedIndex(); 379 | return Double.valueOf(box.getItemText(selection)); 380 | } 381 | 382 | private void addAspect(final AspectType aspectType) { 383 | final Label label = aspectLabels.get(aspectType); 384 | int counter = Integer.parseInt(label.getText()); 385 | counter++; 386 | label.setText(String.valueOf(counter)); 387 | } 388 | 389 | public final void changeHouseSystem(final HouseType houseType) { 390 | this.houseType = houseType; 391 | generateChart(ascendent, epoch, houseType); 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /src/astrochart/client/widgets/TimeEntry.java: -------------------------------------------------------------------------------- 1 | package astrochart.client.widgets; 2 | 3 | import java.util.Date; 4 | import astrochart.client.event.DateUpdatedEvent; 5 | import astrochart.client.util.Constants; 6 | import astrochart.client.util.DateTimeUtil; 7 | import astrochart.shared.enums.time.Month; 8 | import astrochart.shared.enums.time.TimeZone; 9 | import com.google.gwt.event.dom.client.ClickEvent; 10 | import com.google.gwt.event.dom.client.ClickHandler; 11 | import com.google.gwt.event.shared.HandlerManager; 12 | import com.google.gwt.i18n.client.DateTimeFormat; 13 | import com.google.gwt.user.client.DOM; 14 | import com.google.gwt.user.client.ui.Button; 15 | import com.google.gwt.user.client.ui.Composite; 16 | import com.google.gwt.user.client.ui.FlexTable; 17 | import com.google.gwt.user.client.ui.Label; 18 | import com.google.gwt.user.client.ui.ListBox; 19 | import com.google.gwt.user.client.ui.TextBox; 20 | 21 | public class TimeEntry extends Composite { 22 | private static final int HIGHER_BOUNDARY = 2100; 23 | private static final int LOWER_BOUNDARY = 1900; 24 | private final HandlerManager eventBus; 25 | private final DateTimeUtil dateTimeUtil; 26 | private final FlexTable flex = new FlexTable(); 27 | private final TextBox yearTextBox = new TextBox(); 28 | private final ListBox monthListBox = new ListBox(); 29 | private final TextBox dayTextBox = new TextBox(); 30 | private final TextBox hoursTextBox = new TextBox(); 31 | private final TextBox minutesTextBox = new TextBox(); 32 | private final TextBox secondsTextBox = new TextBox(); 33 | private final ListBox timeZoneListBox = new ListBox(); 34 | private final Button updateButton = new Button("Enter"); 35 | private final Label statusLabel = new Label(String.valueOf('\u00A0')); // NBSP 36 | private final DateTimeFormat dateTimeFormat = DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss"); 37 | private int clientOffset; 38 | private Date localDate; // local date of the client, not the ListBox 39 | 40 | private enum Column { 41 | Year(0), 42 | Month(1), 43 | Day(2), 44 | Hours(3), 45 | Minutes(4), 46 | Seconds(5), 47 | Timezone(6), 48 | Action(7); 49 | 50 | private int number; 51 | 52 | Column(final int number) { 53 | this.number = number; 54 | } 55 | 56 | public int getNumber() { 57 | return number; 58 | } 59 | }; 60 | 61 | public TimeEntry(final HandlerManager eventBus, final DateTimeUtil dateTimeUtil) { 62 | this.eventBus = eventBus; 63 | this.dateTimeUtil = dateTimeUtil; 64 | localDate = new Date(); 65 | 66 | for (final Column column : Column.values()) { 67 | flex.setText(0, column.getNumber(), column.name()); 68 | } 69 | 70 | yearTextBox.setWidth("50px"); 71 | flex.setWidget(1, Column.Year.getNumber(), yearTextBox); 72 | for (final Month month : Month.values()) { 73 | monthListBox.addItem(month.name()); 74 | } 75 | flex.setWidget(1, Column.Month.getNumber(), monthListBox); 76 | dayTextBox.setWidth("50px"); 77 | flex.setWidget(1, Column.Day.getNumber(), dayTextBox); 78 | 79 | hoursTextBox.setWidth("50px"); 80 | flex.setWidget(1, Column.Hours.getNumber(), hoursTextBox); 81 | minutesTextBox.setWidth("50px"); 82 | flex.setWidget(1, Column.Minutes.getNumber(), minutesTextBox); 83 | secondsTextBox.setWidth("50px"); 84 | flex.setWidget(1, Column.Seconds.getNumber(), secondsTextBox); 85 | for (final TimeZone zone : TimeZone.values()) { 86 | timeZoneListBox.addItem(zone.getName()); 87 | } 88 | flex.setWidget(1, Column.Timezone.getNumber(), timeZoneListBox); 89 | updateButton.addClickHandler(new ClickHandler() { 90 | @Override 91 | public void onClick(final ClickEvent event) { 92 | updateDate(); 93 | } 94 | }); 95 | flex.setWidget(1, Column.Action.getNumber(), updateButton); 96 | 97 | flex.setWidget(2, 0, statusLabel); 98 | flex.getFlexCellFormatter().setColSpan(2, 0, Column.values().length + 1); 99 | 100 | updateValues(); 101 | updateDate(); 102 | 103 | initWidget(flex); 104 | setStyleName("time-entry"); 105 | } 106 | 107 | private void updateValues() { 108 | yearTextBox.setText(String.valueOf(dateTimeUtil.getYear(localDate))); 109 | int monthListIndex = 0; 110 | for (final Month month : Month.values()) { 111 | if (dateTimeUtil.getMonth(localDate) == month.getNumber()) { 112 | monthListBox.setSelectedIndex(monthListIndex); 113 | } 114 | monthListIndex++; 115 | } 116 | dayTextBox.setText(String.valueOf(dateTimeUtil.getDay(localDate))); 117 | hoursTextBox.setText(String.valueOf(dateTimeUtil.getHours(localDate))); 118 | minutesTextBox.setText(String.valueOf(dateTimeUtil.getMinutes(localDate))); 119 | secondsTextBox.setText(String.valueOf(dateTimeUtil.getSeconds(localDate))); 120 | final double timeZoneOffset = DOM.getElementById("timeZone").getPropertyDouble("value"); 121 | int zoneListIndex = 0; 122 | for (final TimeZone zone : TimeZone.values()) { 123 | if (Double.valueOf(timeZoneOffset * Constants.SECONDS_PER_MINUTE).intValue() == zone.getUtcOffsetMinutes()) { 124 | clientOffset = Double.valueOf(timeZoneOffset * Constants.SECONDS_PER_MINUTE).intValue(); 125 | timeZoneListBox.setSelectedIndex(zoneListIndex); 126 | } 127 | zoneListIndex++; 128 | } 129 | } 130 | 131 | private void updateDate() { 132 | // "yyyy.MM.dd HH:mm:ss" 133 | statusLabel.setText(String.valueOf('\u00A0')); 134 | try { 135 | final StringBuilder dateString = new StringBuilder(); 136 | validateYear(); 137 | dateString.append(yearTextBox.getText()); 138 | dateString.append("."); 139 | final Month month = Month.valueOf(monthListBox.getValue(monthListBox.getSelectedIndex())); 140 | dateString.append(formatToTwoDigits(String.valueOf(month.getNumber()))); 141 | dateString.append("."); 142 | validateDay(); 143 | dateString.append(formatToTwoDigits(dayTextBox.getText())); 144 | dateString.append(" "); 145 | validateHours(); 146 | dateString.append(formatToTwoDigits(hoursTextBox.getText())); 147 | dateString.append(":"); 148 | validateMinutes(); 149 | dateString.append(formatToTwoDigits(minutesTextBox.getText())); 150 | dateString.append(":"); 151 | validateSeconds(); 152 | dateString.append(formatToTwoDigits(secondsTextBox.getText())); 153 | final Date tempDate = dateTimeFormat.parse(dateString.toString()); 154 | final TimeZone timeZone = TimeZone.getTimeZoneForName(timeZoneListBox.getValue(timeZoneListBox.getSelectedIndex())); 155 | // final com.google.gwt.i18n.client.TimeZone tzUtc = 156 | // com.google.gwt.i18n.client.TimeZone.createTimeZone(0); 157 | // final com.google.gwt.i18n.client.TimeZone tz = 158 | // com.google.gwt.i18n.client.TimeZone.createTimeZone(timeZone.getUtcOffsetMinutes()); 159 | final Date boxDate = new Date(tempDate.getTime() - (timeZone.getUtcOffsetMinutes() * Constants.MILLISECONDS_PER_MINUTE)); 160 | localDate = new Date(boxDate.getTime() + (clientOffset * Constants.MILLISECONDS_PER_MINUTE)); 161 | final StringBuilder status = new StringBuilder(); 162 | status.append(dateTimeFormat.format(tempDate)); 163 | status.append(" "); 164 | status.append(timeZone.getName()); 165 | if (timeZone.getUtcOffsetMinutes() != clientOffset) { 166 | status.append(" --> "); 167 | status.append(dateTimeFormat.format(localDate)); 168 | status.append(" UTC+"); 169 | status.append(clientOffset / Constants.SECONDS_PER_MINUTE); 170 | } 171 | if (timeZone.getUtcOffsetMinutes() != 0) { 172 | status.append(" --> "); 173 | status.append(dateTimeFormat.format(boxDate)); 174 | status.append(" UTC "); 175 | } 176 | statusLabel.setText(status.toString()); 177 | eventBus.fireEvent(new DateUpdatedEvent(localDate)); 178 | } catch (final IllegalArgumentException iae) { 179 | statusLabel.setText(iae.getMessage()); 180 | } 181 | } 182 | 183 | private void validateSeconds() { 184 | final int minutes = Integer.valueOf(secondsTextBox.getText()); 185 | if (minutes < 0 || minutes > Constants.MINUTES_PER_HOUR - 1) { 186 | secondsTextBox.setFocus(true); 187 | throw new IllegalArgumentException("Seconds are out of range."); 188 | } 189 | } 190 | 191 | private void validateMinutes() { 192 | final int minutes = Integer.valueOf(minutesTextBox.getText()); 193 | if (minutes < 0 || minutes > Constants.MINUTES_PER_HOUR - 1) { 194 | minutesTextBox.setFocus(true); 195 | throw new IllegalArgumentException("Minutes are out of range."); 196 | } 197 | } 198 | 199 | private void validateHours() { 200 | final int hours = Integer.valueOf(hoursTextBox.getText()); 201 | if (hours < 0 || hours > Constants.HOURS_PER_DAY - 1) { 202 | hoursTextBox.setFocus(true); 203 | throw new IllegalArgumentException("Hour is out of range."); 204 | } 205 | } 206 | 207 | private void validateYear() { 208 | final int year = Integer.valueOf(yearTextBox.getText()); 209 | if (year < LOWER_BOUNDARY || year > HIGHER_BOUNDARY) { 210 | yearTextBox.setFocus(true); 211 | throw new IllegalArgumentException("Year is out of range."); 212 | } 213 | } 214 | 215 | private void validateDay() { 216 | final int day = Integer.valueOf(dayTextBox.getText()); 217 | final Month month = Month.valueOf(monthListBox.getValue(monthListBox.getSelectedIndex())); 218 | if (day < 1 || day > month.getDays()) { 219 | final int year = Integer.valueOf(yearTextBox.getText()); 220 | if (day == month.getDays() + 1 && DateTimeUtil.isLeapYear(year) && month.equals(Month.February)) { 221 | dayTextBox.setFocus(true); 222 | throw new IllegalArgumentException("Day is out of range. (" + year + " is a leap year)."); 223 | } else { 224 | dayTextBox.setFocus(true); 225 | throw new IllegalArgumentException("Day is out of range."); 226 | } 227 | } 228 | } 229 | 230 | private String formatToTwoDigits(final String in) { 231 | if (in.length() == 1) { 232 | return "0" + in; 233 | } else { 234 | return in; 235 | } 236 | } 237 | 238 | public final Date getLocalDate() { 239 | return localDate; 240 | } 241 | 242 | public final String getClientTimezone() { 243 | return " UTC+" + (clientOffset / Constants.MINUTES_PER_HOUR); 244 | } 245 | 246 | public final void updateDate(final Date newUtcDate) { 247 | localDate = newUtcDate; 248 | updateValues(); 249 | int zoneListIndex = 0; 250 | for (final TimeZone zone : TimeZone.values()) { 251 | if (zone.getUtcOffsetMinutes() == 0) { 252 | timeZoneListBox.setSelectedIndex(zoneListIndex); 253 | break; 254 | } 255 | zoneListIndex++; 256 | } 257 | updateDate(); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/astrochart/server/service/AdminServiceImpl.java: -------------------------------------------------------------------------------- 1 | package astrochart.server.service; 2 | 3 | import java.util.logging.Logger; 4 | import javax.jdo.JDOHelper; 5 | import javax.jdo.PersistenceManager; 6 | import javax.jdo.PersistenceManagerFactory; 7 | import astrochart.client.service.AdminService; 8 | import astrochart.shared.data.Epoch; 9 | import com.google.gwt.user.server.rpc.RemoteServiceServlet; 10 | 11 | @SuppressWarnings("serial") 12 | public class AdminServiceImpl extends RemoteServiceServlet implements AdminService { 13 | @SuppressWarnings("unused") 14 | private static final Logger LOG = Logger.getLogger(AdminServiceImpl.class.getName()); 15 | private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional"); 16 | 17 | @Override 18 | public final void saveEpoch(final Epoch epoch) { 19 | System.out.println(epoch); 20 | final PersistenceManager pm = PMF.getPersistenceManager(); 21 | try { 22 | pm.makePersistent(epoch); 23 | // LOG.log(Level.INFO, "Epoch stored: " + epoch); 24 | } finally { 25 | pm.close(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/astrochart/server/service/EpochServiceImpl.java: -------------------------------------------------------------------------------- 1 | package astrochart.server.service; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Collections; 5 | import java.util.Date; 6 | import java.util.List; 7 | import java.util.logging.Logger; 8 | import net.sf.jsr107cache.Cache; 9 | import net.sf.jsr107cache.CacheException; 10 | import net.sf.jsr107cache.CacheManager; 11 | import astrochart.client.service.EpochService; 12 | import astrochart.client.util.Constants; 13 | import astrochart.shared.data.Epoch; 14 | import astrochart.shared.enums.Planet; 15 | import astrochart.shared.exceptions.EpochNotFoundException; 16 | import com.google.appengine.api.datastore.DatastoreService; 17 | import com.google.appengine.api.datastore.DatastoreServiceFactory; 18 | import com.google.appengine.api.datastore.Entity; 19 | import com.google.appengine.api.datastore.FetchOptions; 20 | import com.google.appengine.api.datastore.PreparedQuery; 21 | import com.google.appengine.api.datastore.Query; 22 | import com.google.appengine.api.datastore.Query.SortDirection; 23 | import com.google.gwt.user.server.rpc.RemoteServiceServlet; 24 | 25 | 26 | @SuppressWarnings("serial") 27 | public class EpochServiceImpl extends RemoteServiceServlet implements EpochService { 28 | private static final int TOLERANCE_FACTOR = 10; 29 | private static final int TOLERANCE_DIVISOR = 8; 30 | private static final int MINUTES_PER_HOUR = 60; 31 | private static final int SECONDS_PER_MINUTE = 60; 32 | private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd"); 33 | @SuppressWarnings("unused") 34 | private static final Logger LOG = Logger.getLogger(EpochServiceImpl.class.getName()); 35 | private final DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 36 | 37 | @Override 38 | public final Epoch readEpoch(final Date date) throws EpochNotFoundException { 39 | final Date low = new Date(date.getTime() - ((Constants.MILLISECONDS_PER_DAY * TOLERANCE_FACTOR) / TOLERANCE_DIVISOR)); 40 | final Date med = new Date(date.getTime()); 41 | final Date high = new Date(date.getTime() + ((Constants.MILLISECONDS_PER_DAY * TOLERANCE_FACTOR) / TOLERANCE_DIVISOR)); 42 | 43 | Epoch first = null; 44 | Epoch second = null; 45 | final Epoch result = new Epoch(); 46 | 47 | // try to get Epochs from cache 48 | Cache cache = null; 49 | String firstCacheKey = sdf.format(low); 50 | String medCacheKey = sdf.format(med); 51 | String secondCacheKey = sdf.format(high); 52 | try { 53 | cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap()); 54 | first = (Epoch) cache.get(firstCacheKey); 55 | if (first == null) { 56 | first = (Epoch) cache.get(medCacheKey); 57 | } else { 58 | second = (Epoch) cache.get(medCacheKey); 59 | } 60 | if (second == null) { 61 | second = (Epoch) cache.get(secondCacheKey); 62 | } 63 | } catch (final CacheException e) { 64 | assert true; // ignore 65 | } 66 | 67 | if (first == null || second == null) { 68 | first = new Epoch(); 69 | second = new Epoch(); 70 | final Query q = new Query("Epoch"); 71 | q.addFilter("sidDate", Query.FilterOperator.GREATER_THAN_OR_EQUAL, low); 72 | q.addFilter("sidDate", Query.FilterOperator.LESS_THAN_OR_EQUAL, high); 73 | q.addSort("sidDate", SortDirection.ASCENDING); 74 | final PreparedQuery pq = datastore.prepare(q); 75 | final List entities = pq.asList(FetchOptions.Builder.withLimit(2)); 76 | if (entities.size() < 2) { 77 | throw new EpochNotFoundException(); 78 | } 79 | 80 | final Entity firstEntity = entities.get(0); 81 | final Entity secondEntity = entities.get(1); 82 | 83 | first.setSidDate((Date) firstEntity.getProperty("sidDate")); 84 | second.setSidDate((Date) secondEntity.getProperty("sidDate")); 85 | first.setDay((String) firstEntity.getProperty("day")); 86 | second.setDay((String) secondEntity.getProperty("day")); 87 | for (final Planet planet : Planet.values()) { 88 | first.setPosition(planet, (String) firstEntity.getProperty(planet.name().toLowerCase())); 89 | second.setPosition(planet, (String) secondEntity.getProperty(planet.name().toLowerCase())); 90 | } 91 | } 92 | 93 | // write epochs to cache 94 | if (cache != null) { 95 | cache.put(sdf.format(first.getSidDate()), first); 96 | cache.put(sdf.format(second.getSidDate()), second); 97 | } 98 | 99 | final long firstTs = first.getSidDate().getTime(); 100 | final long originalTs = date.getTime(); 101 | final long secondTs = second.getSidDate().getTime(); 102 | 103 | final long totalDifference = secondTs - firstTs; // --> 100% 104 | final long firstDifference = originalTs - firstTs; 105 | final long secondDifference = secondTs - originalTs; 106 | 107 | result.setSidDate(date); 108 | if (firstDifference < secondDifference) { 109 | // first result is closer to original date 110 | result.setDay(first.getDay()); 111 | } else { 112 | result.setDay(second.getDay()); 113 | } 114 | 115 | for (final Planet planet : Planet.values()) { 116 | if (!planet.equals(Planet.SouthNode)) { 117 | // final String firstToken = (String) 118 | // firstEntity.getProperty(planet.name().toLowerCase()); 119 | // final String secondToken = (String) 120 | // secondEntity.getProperty(planet.name().toLowerCase()); 121 | final String firstToken = first.getPosition(planet); 122 | final String secondToken = second.getPosition(planet); 123 | 124 | final int firstDegrees = Integer.parseInt(firstToken.substring(0, 2)); 125 | final int secondDegrees = Integer.parseInt(secondToken.substring(0, 2)); 126 | final String firstSign = firstToken.substring(2, 4); 127 | final String secondSign = secondToken.substring(2, 4); 128 | final int firstMinutes = Integer.parseInt(firstToken.substring(4, 6)); 129 | final int secondMinutes = Integer.parseInt(secondToken.substring(4, 6)); 130 | 131 | int averageDegrees = 0; 132 | String tokenSign = ""; 133 | int averageMinutes = 0; 134 | long averageTotalMinutes = 0; 135 | if (firstSign.equals(secondSign)) { 136 | tokenSign = firstSign; 137 | //Note: firstDifference and secondDifference are switched in order to weight 138 | //the nearer epoch with the smaller difference more than the further 139 | averageTotalMinutes = ( 140 | ((firstMinutes + (firstDegrees * MINUTES_PER_HOUR)) * secondDifference) 141 | + ((secondMinutes + (secondDegrees * SECONDS_PER_MINUTE)) * firstDifference) 142 | ) / totalDifference; 143 | } else { 144 | if (firstDifference < secondDifference) { 145 | //high degrees 146 | tokenSign = firstSign; 147 | averageTotalMinutes = ( 148 | ((firstMinutes + (firstDegrees * MINUTES_PER_HOUR)) * secondDifference) 149 | + ((secondMinutes + ((secondDegrees + (SECONDS_PER_MINUTE / 2)) * SECONDS_PER_MINUTE)) * firstDifference) 150 | ) / totalDifference; 151 | } else { 152 | //low degrees 153 | tokenSign = secondSign; 154 | averageTotalMinutes = ( 155 | ((firstMinutes + ((firstDegrees + (MINUTES_PER_HOUR / 2)) * MINUTES_PER_HOUR)) * secondDifference) 156 | + ((secondMinutes + (secondDegrees * SECONDS_PER_MINUTE)) * firstDifference) 157 | ) / totalDifference; 158 | } 159 | } 160 | 161 | averageDegrees = (int) averageTotalMinutes / MINUTES_PER_HOUR; 162 | if (averageDegrees >= (MINUTES_PER_HOUR / 2)) { 163 | averageDegrees = averageDegrees - (MINUTES_PER_HOUR / 2); 164 | } 165 | averageMinutes = (int) averageTotalMinutes % MINUTES_PER_HOUR; 166 | final String tokenDegrees = addZeroIfNeeded(String.valueOf(averageDegrees)); 167 | final String tokenMinutes = addZeroIfNeeded(String.valueOf(averageMinutes)); 168 | result.setPosition(planet, tokenDegrees + tokenSign + tokenMinutes); 169 | } 170 | } 171 | 172 | /* 173 | final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); 174 | String firstPercent = (firstDifference * 100 / totalDifference) + "%"; 175 | String secondPercent = (secondDifference * 100 / totalDifference) + "%"; 176 | System.out.println("First: " + sdf.format(first.getSidDate()) + " " + first.toString() + " " + firstPercent); 177 | System.out.println("Result: " + sdf.format(result.getSidDate()) + " " + result.toString() + "<"); 178 | System.out.println("Second: " + sdf.format(second.getSidDate()) + " " + second.toString() + " " + secondPercent); 179 | */ 180 | return result; 181 | } 182 | 183 | private String addZeroIfNeeded(final String value) { 184 | if (value.length() < 2) { 185 | return "0" + value; 186 | } else { 187 | return value; 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/astrochart/server/service/GeocodeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package astrochart.server.service; 2 | 3 | 4 | import java.io.BufferedReader; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | import java.util.logging.Logger; 10 | import astrochart.client.service.GeocodeService; 11 | import astrochart.shared.data.GeocodeData; 12 | import com.google.gson.JsonArray; 13 | import com.google.gson.JsonElement; 14 | import com.google.gson.JsonObject; 15 | import com.google.gson.JsonParser; 16 | import com.google.gwt.user.server.rpc.RemoteServiceServlet; 17 | 18 | 19 | @SuppressWarnings("serial") 20 | public class GeocodeServiceImpl extends RemoteServiceServlet implements GeocodeService { 21 | @SuppressWarnings("unused") 22 | private static final Logger LOG = Logger.getLogger(GeocodeServiceImpl.class.getName()); 23 | 24 | @Override 25 | public final GeocodeData getGeocodeData(final String cityName) { 26 | final String encodedCityName = encode(cityName); 27 | final String geocodeUrl = "http://maps.googleapis.com/maps/api/geocode/json?address=" + encodedCityName + "&sensor=false"; 28 | final GeocodeData result = makeGeocodeRequest(geocodeUrl); 29 | return result; 30 | } 31 | 32 | @Override 33 | public final GeocodeData getGeocodeDataForIp() { 34 | final String ipString = getThreadLocalRequest().getRemoteAddr(); 35 | final String ipGeocodeUrl = "http://freegeoip.net/json/" + ipString; 36 | final GeocodeData result = makeIpGeocodeRequest(ipGeocodeUrl); 37 | return result; 38 | } 39 | 40 | private GeocodeData makeGeocodeRequest(final String geocodeUrl) { 41 | try { 42 | final URL url = new URL(geocodeUrl); 43 | final BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); 44 | final JsonParser parser = new JsonParser(); 45 | final JsonElement element = parser.parse(reader); 46 | reader.close(); 47 | final JsonObject rootObject = element.getAsJsonObject(); 48 | return parseJsonGeocodeResult(rootObject); 49 | } catch (final MalformedURLException e) { 50 | return createErrorGeocode(); 51 | } catch (final IOException e) { 52 | return createErrorGeocode(); 53 | } 54 | } 55 | 56 | private GeocodeData createErrorGeocode() { 57 | final GeocodeData result = new GeocodeData(); 58 | result.setCityName("Error finding location."); 59 | result.setLatitude(0.0D); 60 | result.setLongitude(0.0D); 61 | return result; 62 | } 63 | 64 | private GeocodeData parseJsonGeocodeResult(final JsonObject rootObject) { 65 | final GeocodeData result = new GeocodeData(); 66 | final JsonArray array = rootObject.getAsJsonArray("results"); 67 | if (array.size() > 0) { 68 | final JsonObject firstResult = array.get(0).getAsJsonObject(); 69 | 70 | final JsonElement address = firstResult.get("formatted_address"); 71 | result.setCityName(address.getAsString()); 72 | 73 | final JsonElement geometryElement = firstResult.get("geometry"); 74 | final JsonElement locationElement = geometryElement.getAsJsonObject().get("location"); 75 | 76 | final JsonElement latElement = locationElement.getAsJsonObject().get("lat"); 77 | result.setLatitude(latElement.getAsDouble()); 78 | final JsonElement lngElement = locationElement.getAsJsonObject().get("lng"); 79 | result.setLongitude(lngElement.getAsDouble()); 80 | } else { 81 | result.setCityName("Location not found."); 82 | result.setLatitude(0.0D); 83 | result.setLongitude(0.0D); 84 | } 85 | return result; 86 | } 87 | 88 | private GeocodeData makeIpGeocodeRequest(final String ipGeocodeUrl) { 89 | try { 90 | final URL url = new URL(ipGeocodeUrl); 91 | final BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); 92 | final JsonParser parser = new JsonParser(); 93 | final JsonElement element = parser.parse(reader); 94 | reader.close(); 95 | final JsonObject rootObject = element.getAsJsonObject(); 96 | return parseJsonIpGeocodeResult(rootObject); 97 | } catch (final MalformedURLException e) { 98 | return createErrorGeocode(); 99 | } catch (final IOException e) { 100 | return createErrorGeocode(); 101 | } 102 | } 103 | 104 | private GeocodeData parseJsonIpGeocodeResult(final JsonObject rootObject) { 105 | final GeocodeData result = new GeocodeData(); 106 | final JsonElement cityElement = rootObject.getAsJsonObject().get("city"); 107 | result.setCityName(cityElement.getAsString()); 108 | final JsonElement latElement = rootObject.getAsJsonObject().get("latitude"); 109 | result.setLatitude(latElement.getAsDouble()); 110 | final JsonElement lngElement = rootObject.getAsJsonObject().get("longitude"); 111 | result.setLongitude(lngElement.getAsDouble()); 112 | return result; 113 | } 114 | 115 | private String encode(final String in) { 116 | return in.replaceAll(" ", "%20"); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/astrochart/shared/EquinocticalShaddowLengths.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import astrochart.shared.enums.RashimanaGroup; 6 | import astrochart.shared.enums.ZodiacSign; 7 | 8 | /** 9 | * Lengths of the equinoctial shadow of a Shanku of 12 units at different 10 | * latitudes Values from: http://www.vedicastro.com/astronomy6.asp 11 | */ 12 | public class EquinocticalShaddowLengths { 13 | private static final double CHARAKHANDA_MULTIPLICATOR_1 = 10D; 14 | private static final double CHARAKHANDA_MULTIPLICATOR_2 = 8D; 15 | private static final double CHARAKHANDA_MULTIPLICATOR_3 = 3.3333333333D; 16 | private static final int LATITUDES = 60; 17 | private final Map shaddowLengths = new HashMap(LATITUDES); 18 | 19 | private enum ShaddowLength { 20 | _01(0.21D), _02(0.42D), _03(0.63D), _04(0.84D), _05(1.05D), _06(1.26D), _07(1.47D), _08(1.69D), _09(1.90D), _10(2.11D), 21 | _11(2.33D), _12(2.55D), _13(2.70D), _14(2.99D), _15(3.21D), _16(3.44D), _17(3.66D), _18(3.90D), _19(4.13D), _20(4.37D), 22 | _21(4.60D), _22(4.85D), _23(5.09D), _24(5.34D), _25(5.59D), _26(5.85D), _27(6.11D), _28(6.38D), _29(6.65D), _30(6.93D), 23 | _31(7.21D), _32(7.50D), _33(7.79D), _34(8.09D), _35(8.40D), _36(8.71D), _37(9.04D), _38(9.37D), _39(9.72D), _40(10.06D), 24 | _41(10.43D), _42(10.80D), _43(11.19D), _44(11.58D), _45(12.00D), _46(12.42D), _47(12.87D), _48(13.33D), _49(13.80D), _50(14.30D), 25 | _51(14.82D), _52(15.35D), _53(15.92D), _54(16.52D), _55(17.13D), _56(17.79D), _57(18.46D), _58(19.20D), _59(19.97D), _60(20.78D); 26 | 27 | private final double length; 28 | 29 | ShaddowLength(final double length) { 30 | this.length = length; 31 | } 32 | 33 | public double getLength() { 34 | return length; 35 | } 36 | } 37 | 38 | public EquinocticalShaddowLengths() { 39 | for (final ShaddowLength sl : ShaddowLength.values()) { 40 | shaddowLengths.put(Integer.valueOf(sl.name().substring(1, 3)), Double.valueOf(sl.getLength())); 41 | } 42 | } 43 | 44 | public final double getShaddowLength(final int latitude) { 45 | return shaddowLengths.get(Integer.valueOf(latitude)).doubleValue(); 46 | } 47 | 48 | public final int calculateCharakhandas(final ZodiacSign sign, final int latitude) { 49 | return calculatePalas(sign, latitude) * 6; // in asus 50 | } 51 | 52 | private int calculatePalas(final ZodiacSign sign, final int latitude) { 53 | final double shaddowLenght = getShaddowLength(latitude); 54 | if (RashimanaGroup.I.equals(sign.getRashimanaGroup())) { 55 | return (int) (shaddowLenght * CHARAKHANDA_MULTIPLICATOR_1); 56 | } else if (RashimanaGroup.II.equals(sign.getRashimanaGroup())) { 57 | return (int) (shaddowLenght * CHARAKHANDA_MULTIPLICATOR_2); 58 | } else if (RashimanaGroup.III.equals(sign.getRashimanaGroup())) { 59 | return (int) (shaddowLenght * CHARAKHANDA_MULTIPLICATOR_3); 60 | } else { 61 | throw new IllegalArgumentException("Sign " + sign + " has illegal rashomana group: " + sign.getRashimanaGroup()); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/astrochart/shared/data/Epoch.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.data; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import javax.jdo.annotations.IdentityType; 6 | import javax.jdo.annotations.PersistenceCapable; 7 | import javax.jdo.annotations.Persistent; 8 | import javax.jdo.annotations.PrimaryKey; 9 | import com.google.gwt.i18n.client.NumberFormat; 10 | import astrochart.shared.enums.Planet; 11 | import astrochart.shared.enums.ZodiacSign; 12 | 13 | @PersistenceCapable(identityType = IdentityType.APPLICATION) 14 | public class Epoch implements Serializable { 15 | private static final long serialVersionUID = 546722654874032959L; 16 | private static final double MINUTES_PER_DEGREE = 60D; 17 | private static final double PRECISION = 100D; 18 | 19 | @PrimaryKey 20 | @Persistent 21 | private Long key; // Timestamp of sidereal Date 22 | 23 | @Persistent 24 | private Date sidDate; 25 | @Persistent 26 | private String day; 27 | 28 | @Persistent 29 | private String sun; 30 | @Persistent 31 | private String moon; 32 | @Persistent 33 | private String mercury; 34 | @Persistent 35 | private String venus; 36 | @Persistent 37 | private String mars; 38 | @Persistent 39 | private String jupiter; 40 | @Persistent 41 | private String saturn; 42 | @Persistent 43 | private String uranus; 44 | @Persistent 45 | private String neptune; 46 | @Persistent 47 | private String pluto; 48 | @Persistent 49 | private String node; 50 | 51 | public Epoch() { 52 | } 53 | 54 | public final Long getKey() { 55 | return key; 56 | } 57 | 58 | public final Date getSidDate() { 59 | return sidDate; 60 | } 61 | 62 | public final void setSidDate(final Date sidDate) { 63 | this.sidDate = sidDate; 64 | this.key = sidDate.getTime(); 65 | } 66 | 67 | public final String getDay() { 68 | return day; 69 | } 70 | 71 | public final void setDay(final String day) { 72 | this.day = day; 73 | } 74 | 75 | public final void setPosition(final Planet planet, final String position) { 76 | if (planet.equals(Planet.Sun)) { 77 | sun = position; 78 | } else if (planet.equals(Planet.Moon)) { 79 | moon = position; 80 | } else if (planet.equals(Planet.Mercury)) { 81 | mercury = position; 82 | } else if (planet.equals(Planet.Venus)) { 83 | venus = position; 84 | } else if (planet.equals(Planet.Mars)) { 85 | mars = position; 86 | } else if (planet.equals(Planet.Jupiter)) { 87 | jupiter = position; 88 | } else if (planet.equals(Planet.Saturn)) { 89 | saturn = position; 90 | } else if (planet.equals(Planet.Uranus)) { 91 | uranus = position; 92 | } else if (planet.equals(Planet.Neptune)) { 93 | neptune = position; 94 | } else if (planet.equals(Planet.Pluto)) { 95 | pluto = position; 96 | } else if (planet.equals(Planet.Node)) { 97 | node = position; 98 | } else if (planet.equals(Planet.SouthNode)) { 99 | assert true; // ignore 100 | //throw new IllegalArgumentException("Cannot set south node position."); 101 | } else { 102 | throw new IllegalArgumentException("Planet unknown."); 103 | } 104 | } 105 | 106 | public final String getPosition(final Planet planet) { 107 | if (planet.equals(Planet.Sun)) { 108 | return sun; 109 | } else if (planet.equals(Planet.Moon)) { 110 | return moon; 111 | } else if (planet.equals(Planet.Mercury)) { 112 | return mercury; 113 | } else if (planet.equals(Planet.Venus)) { 114 | return venus; 115 | } else if (planet.equals(Planet.Mars)) { 116 | return mars; 117 | } else if (planet.equals(Planet.Jupiter)) { 118 | return jupiter; 119 | } else if (planet.equals(Planet.Saturn)) { 120 | return saturn; 121 | } else if (planet.equals(Planet.Uranus)) { 122 | return uranus; 123 | } else if (planet.equals(Planet.Neptune)) { 124 | return neptune; 125 | } else if (planet.equals(Planet.Pluto)) { 126 | return pluto; 127 | } else if (planet.equals(Planet.Node)) { 128 | return node; 129 | } else if (planet.equals(Planet.SouthNode)) { 130 | return determineSouthNodePosition(); 131 | } else { 132 | throw new IllegalArgumentException("Planet unknown"); 133 | } 134 | } 135 | 136 | public final int getDegrees(final Planet planet) { 137 | return Integer.parseInt(getPosition(planet).substring(0, 2)); 138 | } 139 | 140 | public final String getSign(final Planet planet) { 141 | return getPosition(planet).substring(2, 4); 142 | } 143 | 144 | public final int getMinutes(final Planet planet) { 145 | return Integer.parseInt(getPosition(planet).substring(4, 6)); 146 | } 147 | 148 | public final double getPreciseDegrees(final Planet planet) { 149 | return getDegrees(planet) + (((getMinutes(planet) * PRECISION) / MINUTES_PER_DEGREE) / PRECISION); 150 | } 151 | 152 | /** 153 | * Determines and returns the position of the south node by evaluating the 154 | * north node position. 155 | */ 156 | private String determineSouthNodePosition() { 157 | final String northNode = getPosition(Planet.Node); 158 | final String northSign = northNode.substring(2, 4); 159 | final String sign = ZodiacSign.valueOfAbbrevistion(northSign).getDescendent(); 160 | final String southNode = northNode.substring(0, 2) + sign + northNode.substring(4, 6); 161 | return southNode; 162 | } 163 | 164 | public final String getPositionString(final Planet planet) { 165 | final StringBuilder builder = new StringBuilder(); 166 | final ZodiacSign sign = ZodiacSign.valueOfAbbrevistion(getSign(planet)); 167 | builder.append(sign.getUnicode()); 168 | builder.append(" "); 169 | builder.append(sign); 170 | builder.append(" "); 171 | final double degree = getPreciseDegrees(planet); 172 | builder.append(NumberFormat.getFormat("0.000").format(degree)); 173 | return builder.toString(); 174 | } 175 | 176 | public final String getPositionDegreeString(final Planet planet) { 177 | final StringBuilder builder = new StringBuilder(); 178 | final ZodiacSign sign = ZodiacSign.valueOfAbbrevistion(getSign(planet)); 179 | builder.append(sign.getUnicode()); 180 | builder.append(" "); 181 | builder.append(sign); 182 | builder.append(" "); 183 | builder.append(getDegrees(planet)); 184 | builder.append(String.valueOf('\u00B0')); 185 | builder.append(" "); 186 | builder.append(getMinutes(planet)); 187 | builder.append(String.valueOf('\u2032')); 188 | return builder.toString(); 189 | } 190 | 191 | public final String toString() { 192 | final StringBuilder builder = new StringBuilder(); 193 | for (final Planet planet : Planet.values()) { 194 | builder.append(planet.name()); 195 | builder.append(":"); 196 | builder.append(getPosition(planet)); 197 | builder.append(" "); 198 | } 199 | return builder.toString(); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/astrochart/shared/data/GeocodeData.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.data; 2 | 3 | import java.io.Serializable; 4 | 5 | public class GeocodeData implements Serializable { 6 | private static final long serialVersionUID = 2353838294439322239L; 7 | 8 | private double latitude; 9 | private double longitude; 10 | private String cityName; 11 | 12 | public GeocodeData() { 13 | } 14 | 15 | public final double getLatitude() { 16 | return latitude; 17 | } 18 | 19 | public final void setLatitude(final double latitude) { 20 | this.latitude = latitude; 21 | } 22 | 23 | public final double getLongitude() { 24 | return longitude; 25 | } 26 | 27 | public final void setLongitude(final double longitude) { 28 | this.longitude = longitude; 29 | } 30 | 31 | public final String getCityName() { 32 | return cityName; 33 | } 34 | 35 | public final void setCityName(final String cityName) { 36 | this.cityName = cityName; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/AspectType.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | public enum AspectType { 4 | Conjunction('\u260C', 0D, 7D, new double[]{1D, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D}), 5 | Sextile('\u26B9', 60D, 5D, new double[]{1D, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D}), //26B9 6 | Quintile('\u0051', 72D, 5D, new double[]{1D, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D}), 7 | Square('\u25A1', 90D, 6D, new double[]{1D, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D}), 8 | Trine('\u25B3', 120D, 5D, new double[]{1D, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D}), 9 | Opposition('\u260D', 180D, 7D, new double[]{1D, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D}); 10 | 11 | // trines are third-order and sextiles sixth-order. sextiles need to be given half the weight 12 | // and about half the orb, and most certainly less orb than quintiles or squares 13 | 14 | private final char unicode; 15 | private final double angle; 16 | private final double defaultOrb; 17 | private final double[] orbs; 18 | 19 | private AspectType(final char unicode, final double angle, final double defaultOrb, final double[] orbs) { 20 | this.unicode = unicode; 21 | this.angle = angle; 22 | this.defaultOrb = defaultOrb; 23 | this.orbs = orbs; 24 | } 25 | 26 | public final char getUnicode() { 27 | return unicode; 28 | } 29 | 30 | public final double getAngle() { 31 | return angle; 32 | } 33 | 34 | public final double[] getOrbs() { 35 | return orbs; 36 | } 37 | 38 | public final double getDefaultOrb() { 39 | return defaultOrb; 40 | } 41 | 42 | public final String toString() { 43 | return name(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/ChartColor.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | public enum ChartColor { 4 | Black("#000000"), 5 | White("#FFFFFF"), 6 | Red("#ED1C24"), 7 | Blue("#3F48CC"), 8 | Yellow("#FFF200"), 9 | Green("#22B14C"); 10 | 11 | private final String hex; 12 | 13 | private ChartColor(final String hex) { 14 | this.hex = hex; 15 | } 16 | 17 | public final String getHex() { 18 | return hex; 19 | } 20 | 21 | public final String toString() { 22 | return name(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/ChartProportions.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | public enum ChartProportions { 4 | Outer(1.00D), 5 | HouseNumber(0.98D), 6 | OuterEclyptic(0.95D), 7 | EclypticCenter(0.85D), 8 | InnerEclyptic(0.75D), 9 | OuterMark(0.72D), 10 | InnerMark(0.70D), 11 | PlanetMark(0.66D), 12 | PlanetSign(0.62D), 13 | Degree(0.55D), 14 | Minute(0.48D), 15 | InnerLine(0.44D), 16 | Inner(0.40D); 17 | 18 | private final double relativeRadius; 19 | 20 | private ChartProportions(final double relativeRadius) { 21 | this.relativeRadius = relativeRadius; 22 | } 23 | 24 | public final double getRelativeRadius() { 25 | return relativeRadius; 26 | } 27 | 28 | public static final int getRadius(final int halfChartSize, final ChartProportions prop) { 29 | return (int) (halfChartSize * prop.getRelativeRadius()); 30 | } 31 | 32 | @Override 33 | public final String toString() { 34 | return this.name(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/HouseType.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | public enum HouseType { 4 | Equal("Equal House"), 5 | WholeSigns("Whole Sign"); 6 | // Placidus("Placidus"), //http://groups.google.com/group/alt.astrology.moderated/browse_thread/thread/5cf05d6fe8eabb52/17e0c6282d8c7dce?lnk=raot 7 | // Campanus, 8 | // Regiomontanus, 9 | // KochHousesSystem; 10 | 11 | private final String name; 12 | 13 | private HouseType(final String name) { 14 | this.name = name; 15 | } 16 | 17 | public final String getName() { 18 | return name; 19 | } 20 | 21 | public final String toString() { 22 | return name(); 23 | } 24 | 25 | public static HouseType getTypeForName(final String name) { 26 | for (final HouseType type : HouseType.values()) { 27 | if (type.getName().equals(name)) { 28 | return type; 29 | } 30 | } 31 | throw new IllegalArgumentException(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/Planet.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | public enum Planet { 4 | Sun(3, '\u2609', true, false), 5 | Moon(4, '\u263e', true, false), 6 | Node(13, '\u260A', false, false), //ascending 7 | SouthNode(14, '\u260B', false, false), //descending 8 | Mercury(5, '\u263f', true, false), 9 | Venus(6, '\u2640', true, false), 10 | Mars(7, '\u2642', true, false), 11 | Jupiter(8, '\u2643', true, false), 12 | Saturn(9, '\u2644', true, false), 13 | Uranus(10, '\u2645', true, true), 14 | Neptune(11, '\u2646', true, true), 15 | Pluto(12, '\u2647', true, true); 16 | 17 | private final int token; 18 | private final char unicode; 19 | private final boolean isBody; 20 | private final boolean isOuter; 21 | 22 | private Planet(final int token, final char unicode, final boolean isBody, final boolean isOuter) { 23 | this.token = token; 24 | this.unicode = unicode; 25 | this.isBody = isBody; 26 | this.isOuter = isOuter; 27 | } 28 | 29 | public final int getToken() { 30 | return token; 31 | } 32 | 33 | public final char getUnicode() { 34 | return unicode; 35 | } 36 | 37 | public final boolean isBody() { 38 | return isBody; 39 | } 40 | 41 | public final boolean isOuter() { 42 | return isOuter; 43 | } 44 | 45 | @Override 46 | public final String toString() { 47 | return this.name(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/RashimanaGroup.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | /** 4 | * compare: http://www.vedicastro.com/astronomy6.asp 5 | */ 6 | public enum RashimanaGroup { 7 | I(1674), II(1795), III(1931); 8 | 9 | private final int equatorialAsus; 10 | 11 | private RashimanaGroup(final int equatorialAsus) { 12 | this.equatorialAsus = equatorialAsus; 13 | } 14 | 15 | public final int getEquatorialAsus() { 16 | return equatorialAsus; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/Weekday.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | public enum Weekday { 4 | Monday("Mo"), Tuesday("Tu"), Wednesday("We"), Thursday("Th"), Friday("Fr"), Saturday("Sa"), Sunday("Su"); 5 | 6 | private final String abbreviation; 7 | 8 | private Weekday(final String abbreviation) { 9 | this.abbreviation = abbreviation; 10 | } 11 | 12 | public final String getAbbreviation() { 13 | return abbreviation; 14 | } 15 | 16 | @Override 17 | public final String toString() { 18 | return this.name(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/ZodiacSign.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums; 2 | 3 | 4 | public enum ZodiacSign { 5 | Aries(0, ChartColor.Red, '\u2648', "AR", "LI", RashimanaGroup.I, false), 6 | Taurus(30, ChartColor.Green, '\u2649', "TA", "SC", RashimanaGroup.II, false), 7 | Gemini(60, ChartColor.Yellow, '\u264A', "GE", "SG", RashimanaGroup.III, false), 8 | Cancer(90, ChartColor.Blue, '\u264B', "CN", "CP", RashimanaGroup.III, true), 9 | Leo(120, ChartColor.Red, '\u264C', "LE", "AQ", RashimanaGroup.II, true), 10 | Virgo(150, ChartColor.Green, '\u264D', "VI", "PI", RashimanaGroup.I, true), 11 | Libra(180, ChartColor.Yellow, '\u264E', "LI", "AR", RashimanaGroup.I, true), 12 | Scorpio(210, ChartColor.Blue, '\u264F', "SC", "TA", RashimanaGroup.II, true), 13 | Sagittaurius(240, ChartColor.Red, '\u2650', "SG", "GE", RashimanaGroup.III, true), 14 | Capricorn(270, ChartColor.Green, '\u2651', "CP", "CN", RashimanaGroup.III, false), 15 | Aquarius(300, ChartColor.Yellow, '\u2652', "AQ", "LE", RashimanaGroup.II, false), 16 | Pisces(330, ChartColor.Blue, '\u2653', "PI", "VI", RashimanaGroup.I, false); 17 | 18 | private static final int DEGREES_PER_SIGN = 30; 19 | private final int eclipticLongitude; 20 | private final ChartColor color; 21 | private final char unicode; 22 | private final String abbreviation; 23 | private final String descendent; 24 | private final RashimanaGroup rashimanaGroup; 25 | private final boolean hasLongAscension; 26 | 27 | private ZodiacSign(final int eclipticLongitude, final ChartColor color, final char unicode, final String abbreviation, final String descendent, 28 | final RashimanaGroup rashimanaGroup, final boolean hasLongAscension) { 29 | this.eclipticLongitude = eclipticLongitude; 30 | this.color = color; 31 | this.unicode = unicode; 32 | this.abbreviation = abbreviation; 33 | this.descendent = descendent; 34 | this.rashimanaGroup = rashimanaGroup; 35 | this.hasLongAscension = hasLongAscension; 36 | } 37 | 38 | public static final ZodiacSign getSignAtDegree(final double degree) { 39 | for (final ZodiacSign sign : ZodiacSign.values()) { 40 | if (degree >= sign.getEclipticLongitude() && degree < sign.getEclipticLongitude() + DEGREES_PER_SIGN) { 41 | return sign; 42 | } 43 | } 44 | throw new IllegalArgumentException("Value out of range: " + degree); 45 | } 46 | 47 | public final int getEclipticLongitude() { 48 | return eclipticLongitude; 49 | } 50 | 51 | public final ChartColor getColor() { 52 | return color; 53 | } 54 | 55 | public final char getUnicode() { 56 | return unicode; 57 | } 58 | 59 | public final String getAbbreviation() { 60 | return abbreviation; 61 | } 62 | 63 | public final String getDescendent() { 64 | return descendent; 65 | } 66 | 67 | public final RashimanaGroup getRashimanaGroup() { 68 | return rashimanaGroup; 69 | } 70 | 71 | public final boolean hasLongAscension() { 72 | return hasLongAscension; 73 | } 74 | 75 | public static final ZodiacSign valueOfAbbrevistion(final String abbreviation) { 76 | for (final ZodiacSign sign : ZodiacSign.values()) { 77 | if (sign.getAbbreviation().equals(abbreviation)) { 78 | return sign; 79 | } 80 | } 81 | throw new IllegalArgumentException("Fail: Abbreviation unknown: " + abbreviation); 82 | } 83 | 84 | @Override 85 | public final String toString() { 86 | return this.name(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/time/Month.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums.time; 2 | 3 | public enum Month { 4 | January(1, 31), 5 | February(2, 28), // 29 days in leap years 6 | March(3, 31), 7 | April(4, 30), 8 | May(5, 31), 9 | June(6, 30), 10 | July(7, 31), 11 | August(8, 31), 12 | September(9, 30), 13 | October(10, 31), 14 | November(11, 30), 15 | December(12, 31); 16 | 17 | private final int number; 18 | private final int days; 19 | 20 | private Month(final int number, final int days) { 21 | this.number = number; 22 | this.days = days; 23 | } 24 | 25 | public final int getNumber() { 26 | return number; 27 | } 28 | 29 | public final int getDays() { 30 | return days; 31 | } 32 | 33 | @Override 34 | public final String toString() { 35 | return this.name(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/astrochart/shared/enums/time/TimeZone.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.enums.time; 2 | 3 | public enum TimeZone { 4 | UTC_12(-720, "UTC-12:00", "-1200"), 5 | UTC_11(-660, "UTC-11:00", "-1100"), 6 | UTC_10(-600, "UTC-10:00", "-1000"), 7 | UTC_930(-570, "UTC-9:30", "-0930"), 8 | UTC_9(-540, "UTC-9:00", "-0900"), 9 | UTC_8(-480, "UTC-8:00", "-0800"), 10 | UTC_7(-420, "UTC-7:00", "-0700"), 11 | UTC_6(-360, "UTC-6:00", "-0600"), 12 | UTC_5(-300, "UTC-5:00", "-0500"), 13 | UTC_430(-270, "UTC-4:30", "-0430"), 14 | UTC_4(-240, "UTC-4:00", "-0400"), 15 | UTC_330(-210, "UTC-3:30", "-0330"), 16 | UTC_3(-180, "UTC-3:00", "-0300"), 17 | UTC_2(-120, "UTC-2:00", "-0200"), 18 | UTC_1(-60, "UTC-1:00", "-0100"), 19 | UTC(0, "UTC", "+0000"), 20 | UTC1(60, "UTC+1:00", "+0100"), 21 | UTC2(120, "UTC+2:00", "+0200"), 22 | UTC3(180, "UTC+3:00", "+0300"), 23 | UTC330(210, "UTC+3:30", "+0330"), 24 | UTC4(240, "UTC+4:00", "+0400"), 25 | UTC430(270, "UTC+4:30", "+0430"), 26 | UTC5(300, "UTC+5:00", "+0500"), 27 | UTC530(330, "UTC+5:30", "+0530"), 28 | UTC545(345, "UTC+5:45", "+0545"), 29 | UTC6(360, "UTC+6:00", "+0600"), 30 | UTC630(390, "UTC+6:30", "+0630"), 31 | UTC7(420, "UTC+7:00", "+0700"), 32 | UTC8(480, "UTC+8:00", "+0800"), 33 | UTC9(540, "UTC+9:00", "+0900"), 34 | UTC930(570, "UTC+9:30", "+0930"), 35 | UTC10(600, "UTC+10:00", "+1000"), 36 | UTC1030(630, "UTC+10:30", "+1030"), 37 | UTC11(660, "UTC+11:00", "+1100"), 38 | UTC1130(690, "UTC+11:30", "+1130"), 39 | UTC12(720, "UTC+12:00", "+1200"), 40 | UTC1245(765, "UTC+12:45", "+1245"), 41 | UTC13(780, "UTC+13:00", "+1300"), 42 | UTC14(840, "UTC+14:00", "+1400"); 43 | 44 | private final int utcOffsetMinutes; 45 | private final String name; 46 | private final String zone; 47 | 48 | private TimeZone(final int utcOffsetMinutes, final String name, final String zone) { 49 | this.utcOffsetMinutes = utcOffsetMinutes; 50 | this.name = name; 51 | this.zone = zone; 52 | } 53 | 54 | public final int getUtcOffsetMinutes() { 55 | return utcOffsetMinutes; 56 | } 57 | 58 | public final String getName() { 59 | return name; 60 | } 61 | 62 | public final String getZone() { 63 | return zone; 64 | } 65 | 66 | public static final TimeZone getTimeZoneForName(final String name) { 67 | for (final TimeZone timeZone : TimeZone.values()) { 68 | if (timeZone.getName().equals(name)) { 69 | return timeZone; 70 | } 71 | } 72 | throw new IllegalArgumentException("No timezone for name " + name + " found."); 73 | } 74 | 75 | @Override 76 | public final String toString() { 77 | return this.name; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/astrochart/shared/exceptions/EpochNotFoundException.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.exceptions; 2 | 3 | public class EpochNotFoundException extends Exception { 4 | private static final long serialVersionUID = 769463999415154553L; 5 | } 6 | -------------------------------------------------------------------------------- /src/astrochart/shared/wrappers/AscendentAndOffset.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.wrappers; 2 | 3 | import com.google.gwt.i18n.client.NumberFormat; 4 | import astrochart.shared.enums.ZodiacSign; 5 | 6 | public class AscendentAndOffset { 7 | private final ZodiacSign ascendent; 8 | private final double offset; 9 | private final double midheaven; 10 | 11 | public AscendentAndOffset(final ZodiacSign ascendent, final double offset, final double midheaven) { 12 | this.ascendent = ascendent; 13 | this.offset = offset; 14 | this.midheaven = midheaven; 15 | } 16 | 17 | public final ZodiacSign getAscendent() { 18 | return ascendent; 19 | } 20 | 21 | public final double getOffset() { 22 | return offset; 23 | } 24 | 25 | public final String getFormattedOffset() { 26 | return NumberFormat.getFormat("0.00").format(offset) + String.valueOf('\u00B0'); 27 | } 28 | 29 | public final double getMidheaven() { 30 | return midheaven; 31 | } 32 | 33 | public final String getFormattedMidheaven() { 34 | return NumberFormat.getFormat("0.00").format(midheaven) + String.valueOf('\u00B0'); 35 | } 36 | 37 | public final String toString() { 38 | return ascendent + " at " + NumberFormat.getFormat("0.000").format(offset); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/astrochart/shared/wrappers/BodyPosition.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.wrappers; 2 | 3 | import com.google.gwt.i18n.client.NumberFormat; 4 | 5 | public class BodyPosition { 6 | private final double azimuth; 7 | private final double height; 8 | 9 | public BodyPosition(final double azimuth, final double height) { 10 | this.azimuth = azimuth; 11 | this.height = height; 12 | } 13 | 14 | public final double getAzimuth() { 15 | return azimuth; 16 | } 17 | 18 | public final double getHeight() { 19 | return height; 20 | } 21 | 22 | public final String toString() { 23 | final StringBuilder builder = new StringBuilder(); 24 | builder.append("Azimuth: "); 25 | builder.append(NumberFormat.getFormat("0.000").format(azimuth)); 26 | builder.append(" Height: "); 27 | builder.append(NumberFormat.getFormat("0.000").format(height)); 28 | return builder.toString(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/astrochart/shared/wrappers/RiseAndSet.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.wrappers; 2 | 3 | import java.util.Date; 4 | 5 | public class RiseAndSet { 6 | private final Date rise; 7 | private final Date set; 8 | 9 | public RiseAndSet(final Date rise, final Date set) { 10 | this.rise = rise; 11 | this.set = set; 12 | } 13 | 14 | public final Date getRise() { 15 | return rise; 16 | } 17 | 18 | public final Date getSet() { 19 | return set; 20 | } 21 | 22 | public final String toString() { 23 | return "rise: " + rise + " set: " + set; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/astrochart/shared/wrappers/TextPosition.java: -------------------------------------------------------------------------------- 1 | package astrochart.shared.wrappers; 2 | 3 | public class TextPosition { 4 | private final String text; 5 | private final double x; 6 | private final double y; 7 | 8 | public TextPosition(final String text, final double x, final double y) { 9 | this.text = text; 10 | this.x = x; 11 | this.y = y; 12 | } 13 | 14 | public final String getText() { 15 | return text; 16 | } 17 | 18 | public final double getX() { 19 | return x; 20 | } 21 | 22 | public final double getY() { 23 | return y; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/log4j.properties: -------------------------------------------------------------------------------- 1 | # To use this configuration, deploy it into your application's WEB-INF/classes 2 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 3 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n 5 | log4j.category.DataNucleus.JDO=WARN, A1 6 | log4j.category.DataNucleus.Persistence=WARN, A1 7 | log4j.category.DataNucleus.Cache=WARN, A1 8 | log4j.category.DataNucleus.MetaData=WARN, A1 9 | log4j.category.DataNucleus.General=WARN, A1 10 | log4j.category.DataNucleus.Utility=WARN, A1 11 | log4j.category.DataNucleus.Transaction=WARN, A1 12 | log4j.category.DataNucleus.Datastore=WARN, A1 13 | log4j.category.DataNucleus.ClassLoading=WARN, A1 14 | log4j.category.DataNucleus.Plugin=WARN, A1 15 | log4j.category.DataNucleus.ValueGeneration=WARN, A1 16 | log4j.category.DataNucleus.Enhancer=WARN, A1 17 | log4j.category.DataNucleus.SchemaTool=WARN, A1 18 | -------------------------------------------------------------------------------- /test/astrochart/client/AstroChartTestSuite.java: -------------------------------------------------------------------------------- 1 | package astrochart.client; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestSuite; 5 | import com.google.gwt.junit.tools.GWTTestSuite; 6 | 7 | public class AstroChartTestSuite extends GWTTestSuite { 8 | public static Test suite() { 9 | final TestSuite suite = new TestSuite("All tests."); 10 | suite.addTestSuite(AstrologyUtilTester.class); 11 | suite.addTestSuite(DateTimeUtilTester.class); 12 | return suite; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/astrochart/client/AstrologyUtilTester.java: -------------------------------------------------------------------------------- 1 | package astrochart.client; 2 | 3 | import java.util.Date; 4 | import astrochart.client.util.AstrologyUtil; 5 | import astrochart.client.util.Constants; 6 | import astrochart.client.util.DateTimeUtil; 7 | import astrochart.shared.enums.ZodiacSign; 8 | import astrochart.shared.wrappers.AscendentAndOffset; 9 | import astrochart.shared.wrappers.BodyPosition; 10 | import astrochart.shared.wrappers.RiseAndSet; 11 | import com.google.gwt.i18n.client.DateTimeFormat; 12 | import com.google.gwt.i18n.client.NumberFormat; 13 | import com.google.gwt.i18n.client.TimeZone; 14 | import com.google.gwt.junit.client.GWTTestCase; 15 | 16 | 17 | public class AstrologyUtilTester extends GWTTestCase { 18 | static final long SIXTH_OF_AUGUST_2006 = 1154844000000L; //2006.08.06 06:00:00 +0000 = 08:00:00 MESZ 19 | static final long EIGHT_OF_MARCH_2012 = 1331200800000L; //2012.03.08 10:00:00 +0000 20 | 21 | private AstrologyUtil astrologyUtil; 22 | private DateTimeUtil dateTimeUtil; 23 | 24 | public final void gwtSetUp() throws Exception { 25 | astrologyUtil = new AstrologyUtil(); 26 | dateTimeUtil = new DateTimeUtil(); 27 | } 28 | 29 | /** 30 | * http://de.wikipedia.org/wiki/Sonnenstand#Rechen-Beispiel 31 | * @throws Exception 32 | */ 33 | public final void testSunPosition() throws Exception { 34 | final Date date = new Date(SIXTH_OF_AUGUST_2006); 35 | final double jd = dateTimeUtil.getJdTimeDate(date); 36 | assertEquals(2453953.75D, jd); 37 | 38 | final double jdNumber = dateTimeUtil.calculateJulianDayNumberFromJd(jd); 39 | assertEquals(2408.75D, jdNumber); 40 | 41 | final double eclipticLongitude = astrologyUtil.calculateEclipticLongitude(jdNumber); 42 | assertEquals(2654.63817475D, eclipticLongitude); 43 | assertEquals(134.63817474999996D, eclipticLongitude % 360D); 44 | 45 | final double meanAnomaly = astrologyUtil.calculateMeanAnomaly(jdNumber); 46 | assertEquals(2731.5927226249996D, meanAnomaly); 47 | assertEquals(211.59272262499962D, meanAnomaly % 360D); 48 | 49 | double eclipticalLength = astrologyUtil.calculateEclipticalLength(eclipticLongitude, meanAnomaly); 50 | // assertEquals(133.653D, eclipticalLength); //according to wiki 51 | assertEquals(133.63630794764566D, eclipticalLength); // result for full formuls 52 | 53 | eclipticalLength = 133.653D; // fix 54 | 55 | final double eclipticInclination = astrologyUtil.calculateEclipticInclination(jdNumber); 56 | assertEquals(23.4380365D, eclipticInclination); 57 | 58 | final double rightAscension = astrologyUtil.calculateRightAscension(eclipticInclination, eclipticalLength); 59 | assertEquals(136.11916738220359D, rightAscension); 60 | 61 | final double declination = astrologyUtil.calculateDeclination(eclipticInclination, eclipticalLength); 62 | assertEquals(16.72572957829604D, declination); 63 | 64 | final double jdo = dateTimeUtil.getJulianDayNumberTimeDropped(date); 65 | assertEquals(2453953.5D, jdo); 66 | 67 | final double julianCenturies = dateTimeUtil.getJulianCenturiesSinceJ2000(jdo); 68 | assertEquals(0.06594113620807666D, julianCenturies); 69 | 70 | final double decimalHours = dateTimeUtil.getDecimalHours(date); 71 | assertEquals(6.0D, decimalHours); 72 | final double starTimeHours = dateTimeUtil.calculateStarTimeHours(julianCenturies, decimalHours); 73 | assertEquals(170.9759163173169D, starTimeHours); 74 | final double starTimeDegrees = dateTimeUtil.convertHoursToDegree(starTimeHours); 75 | assertEquals(2564.6387447597535D, starTimeDegrees); 76 | 77 | final double latitude = 48.1D; // For Munich 78 | final double longitude = 11.6D; // For Munich 79 | 80 | final double localJulianDeg = astrologyUtil.calculateVeneralEquinoxDegrees(starTimeDegrees, longitude); 81 | assertEquals(56.238744759753445D, localJulianDeg); 82 | 83 | final double hourAngle = astrologyUtil.calculateHourAngle(localJulianDeg, rightAscension); 84 | assertEquals(-79.88042262245014, hourAngle); 85 | 86 | final double azimuth = astrologyUtil.calculateAzimuth(hourAngle, latitude, declination); 87 | assertEquals(265.93806263966246D, azimuth); 88 | final double heightAngle = astrologyUtil.calculateHeightAngle(hourAngle, latitude, declination); 89 | assertEquals(19.06143926382523D, heightAngle); 90 | 91 | final double refHeight = astrologyUtil.calculateRefractionDegrees(heightAngle); 92 | assertEquals(19.109478922873596D, refHeight); 93 | } 94 | 95 | public final void testFullSunPosition() throws Exception { 96 | final Date date = new Date(SIXTH_OF_AUGUST_2006); 97 | final double latitude = 48.1D; // For Munich 98 | final double longitude = 11.6D; // For Munich 99 | final BodyPosition position = astrologyUtil.calculateSunPosition(date, latitude, longitude); 100 | assertEquals(265.94669695311495D, position.getAzimuth()); 101 | assertEquals(19.124002077105114D, position.getHeight()); 102 | } 103 | 104 | public final void testSunsetAndSunrise() throws Exception { 105 | final Date date = new Date(EIGHT_OF_MARCH_2012); 106 | final double latitude = 39.040759D; 107 | final double longitude = 77.04876D; 108 | 109 | final double julianDate = dateTimeUtil.calculateJulianDate(date); 110 | assertEquals(2455995.0D, julianDate); 111 | final double julianCycle = astrologyUtil.calculateAccurateJulianCycle(julianDate, longitude); 112 | assertEquals(4450.0D, julianCycle); 113 | final double solarNoonApprox = astrologyUtil.calculateApproxSolarNoon(julianCycle, longitude); 114 | assertEquals(2455995.214924333D, solarNoonApprox); 115 | final double meanSolarAnomaly = astrologyUtil.calculateAccurateMeanAnomaly(solarNoonApprox); 116 | System.out.println("meanSolarAnomaly: " + meanSolarAnomaly); 117 | assertEquals(63.66217548293298D, meanSolarAnomaly); 118 | final double equationOfCenter = astrologyUtil.calculateEquationOfCenter(meanSolarAnomaly); 119 | assertEquals(1.731878909721004D, equationOfCenter); 120 | final double solarEclipticalLongitude = astrologyUtil.calculateSolarEclipticLongitude(meanSolarAnomaly, equationOfCenter); 121 | assertEquals(348.331254392654D, solarEclipticalLongitude); 122 | final double solarNoonTransit = astrologyUtil.calculateSolarNoonTransit(solarNoonApprox, meanSolarAnomaly, solarEclipticalLongitude); 123 | assertEquals(2455995.22240757D, solarNoonTransit); 124 | 125 | final double accurateMeanSolarAnomaly = astrologyUtil.calculateAccurateMeanAnomalyRecursive(solarNoonApprox, meanSolarAnomaly, 126 | solarNoonTransit); 127 | assertEquals(63.66954963102398D, accurateMeanSolarAnomaly); 128 | assertEquals(63.66954963102398D, astrologyUtil.getMeanSolarNoonAnomaly()); 129 | assertEquals(1.731984996483541D, astrologyUtil.getEquationOfCenter()); 130 | assertEquals(348.3387346275075D, astrologyUtil.getSolarEclipticalLongitude()); 131 | assertEquals(2455995.2224062183D, astrologyUtil.getSolarNoonTransit()); 132 | 133 | final Date transit = dateTimeUtil.convertJdToDate(astrologyUtil.getSolarNoonTransit()); 134 | assertEquals("2012.03.08 17:20:15", dateTimeUtil.formatDateAsUtc(transit)); 135 | 136 | final double solarDeclination = astrologyUtil.calculateSolarDeclination(astrologyUtil.getSolarEclipticalLongitude()); 137 | assertEquals(-4.6135967684537365D, solarDeclination); 138 | final double hourAngle = astrologyUtil.calculateExactHourAngle(latitude, solarDeclination); 139 | assertEquals(87.32152540998553D, hourAngle); 140 | final double solarNoonSecondApprox = astrologyUtil.calculateSolarNoonSecondApprox(hourAngle, longitude, julianCycle); 141 | assertEquals(2455995.457484126D, solarNoonSecondApprox); 142 | 143 | final double sunset = astrologyUtil.calculateSunset(solarNoonSecondApprox, accurateMeanSolarAnomaly, 144 | astrologyUtil.getSolarEclipticalLongitude()); 145 | assertEquals(2455995.4649660112D, sunset); 146 | final double sunrise = astrologyUtil.calculateSunrise(sunset, astrologyUtil.getSolarNoonTransit()); 147 | assertEquals(2455994.9798464254D, sunrise); 148 | } 149 | 150 | public final void testFullSunsetAndSunrise() throws Exception { 151 | final Date date = new Date(EIGHT_OF_MARCH_2012); 152 | final double latitude = 39.040759D; // for GMT -5 153 | final double longitude = 77.04876D; // for GMT -5 154 | final RiseAndSet ras = astrologyUtil.calculateSunRiseAndSet(date, latitude, longitude); 155 | 156 | final TimeZone timeZone = TimeZone.createTimeZone(300); // GMT -5 157 | final String originalDate = DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss Z").format(date, timeZone); 158 | final String sunriseDate = DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss Z").format(ras.getRise(), timeZone); 159 | final String sunsetDate = DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss Z").format(ras.getSet(), timeZone); 160 | assertEquals("2012.03.08 05:00:00 -0500", originalDate); 161 | assertEquals("2012.03.08 06:30:58 -0500", sunriseDate); 162 | assertEquals("2012.03.08 18:09:33 -0500", sunsetDate); 163 | } 164 | 165 | /** 166 | * http://de.wikipedia.org/wiki/Aszendent_%28Astrologie%29#Beispiele 167 | * @throws Exception 168 | */ 169 | public final void testTropicalAscendent() throws Exception { 170 | final Date firstDate = new Date(437317440000L); // 1983.11.10 13:04:00 +0000 171 | final double firstLongitude = 16D; 172 | final double firstLatitude = 48D; 173 | final double firstJd = dateTimeUtil.getJdTimeDate(firstDate); 174 | assertEquals(2445649.0444444446D, firstJd); 175 | final double firstCents = dateTimeUtil.getJulianCenturiesSinceJ2000(firstJd); 176 | assertEquals(-0.16142246558673268D, firstCents); 177 | final double firstSiderealDegrees = dateTimeUtil.getSiderealDegrees(firstJd); 178 | assertEquals(-2128074.87242789D, firstSiderealDegrees); 179 | final double firstLocalSiderealDegrees = dateTimeUtil.getLocalSiderealDegrees(firstSiderealDegrees, firstLongitude); 180 | assertEquals(261.12757210992277D, firstLocalSiderealDegrees); 181 | 182 | final double firstEclipticLongitudeTan = astrologyUtil.calculateEclipticLongitudeJ2000Tangens(firstLocalSiderealDegrees, firstLatitude); 183 | assertEquals(-0.3318826228021096D, firstEclipticLongitudeTan); // -0,331882633 difference due to more accurate inclination 184 | final double firstS1 = astrologyUtil.getFirstHorizontEclipticSection(firstEclipticLongitudeTan); 185 | assertEquals(161.63989133761655D, firstS1); 186 | final double firstS2 = astrologyUtil.getSecondHorizontEclipticSection(firstEclipticLongitudeTan); 187 | assertEquals(341.6398913376165D, firstS2); 188 | final boolean firstReturnDescendent = astrologyUtil.returnDescendent(firstLocalSiderealDegrees); 189 | assertTrue(firstReturnDescendent); 190 | 191 | final ZodiacSign firstSign = astrologyUtil.returnSign(firstS1, firstS2, firstReturnDescendent); 192 | assertEquals(ZodiacSign.Pisces, firstSign); 193 | final double firstPosition = astrologyUtil.returnPosition(firstS1, firstS2, firstReturnDescendent); 194 | assertEquals(11.639891337616518D, firstPosition); 195 | // /////////////////////////////////////////////// 196 | 197 | final Date secondDate = new Date(534640320000L); // 1986.12.10 23:12:00 +0000 198 | final double secondLongitude = -27D; 199 | final double secondLatitude = -61D; 200 | 201 | final double secondJd = dateTimeUtil.getJdTimeDate(secondDate); 202 | assertEquals(2446775.466666667D, secondJd); 203 | final double secondCents = dateTimeUtil.getJulianCenturiesSinceJ2000(secondJd); 204 | assertEquals(-0.13058270590919122D, secondCents); 205 | final double secondSiderealDegrees = dateTimeUtil.getSiderealDegrees(secondJd); 206 | assertEquals(-1721452.6173363847D, secondSiderealDegrees); 207 | final double secondLocalSiderealDegrees = dateTimeUtil.getLocalSiderealDegrees(secondSiderealDegrees, secondLongitude); 208 | assertEquals(40.38266361528076D, secondLocalSiderealDegrees); 209 | 210 | final double secondEclipticLongitudeTan = astrologyUtil.calculateEclipticLongitudeJ2000Tangens(secondLocalSiderealDegrees, secondLatitude); 211 | assertEquals(6.183810457084861D, secondEclipticLongitudeTan); 212 | 213 | final double secondS1 = astrologyUtil.getFirstHorizontEclipticSection(secondEclipticLongitudeTan); 214 | assertEquals(80.81407386747117D, secondS1); 215 | final double secondS2 = astrologyUtil.getSecondHorizontEclipticSection(secondEclipticLongitudeTan); 216 | assertEquals(260.81407386747117D, secondS2); 217 | final boolean secondReturnDescendent = astrologyUtil.returnDescendent(secondLocalSiderealDegrees); 218 | assertFalse(secondReturnDescendent); 219 | 220 | final ZodiacSign secondSign = astrologyUtil.returnSign(secondS1, secondS2, secondReturnDescendent); 221 | assertEquals(ZodiacSign.Gemini, secondSign); 222 | final double secondPosition = astrologyUtil.returnPosition(secondS1, secondS2, secondReturnDescendent); 223 | assertEquals(20.814073867471166D, secondPosition); 224 | // /////////////////////////////////////////////// 225 | 226 | final Date thirdDate = new Date(1607214420000L); // 2020.12.06 00:27:00 +0000 227 | final double thirdLongitude = -6D; 228 | final double thirdLatitude = -14D; 229 | 230 | final double thirdJd = dateTimeUtil.getJdTimeDate(thirdDate); 231 | assertEquals(2459189.51875D, thirdJd); 232 | final double thirdCents = dateTimeUtil.getJulianCenturiesSinceJ2000(thirdJd); 233 | assertEquals(0.20929551676933097D, thirdCents); 234 | final double thirdSiderealDegrees = dateTimeUtil.getSiderealDegrees(thirdJd); 235 | assertEquals(2759842.0103965397D, thirdSiderealDegrees); 236 | final double thirdLocalSiderealDegrees = dateTimeUtil.getLocalSiderealDegrees(thirdSiderealDegrees, thirdLongitude); 237 | assertEquals(76.01039653969929D, thirdLocalSiderealDegrees); 238 | 239 | final double thirdEclipticLongitudeTan = astrologyUtil.calculateEclipticLongitudeJ2000Tangens(thirdLocalSiderealDegrees, thirdLatitude); 240 | assertEquals(-0.30558489581660087D, thirdEclipticLongitudeTan); 241 | 242 | final double thirdS1 = astrologyUtil.getFirstHorizontEclipticSection(thirdEclipticLongitudeTan); 243 | assertEquals(163.0076391971394D, thirdS1); 244 | final double thirdS2 = astrologyUtil.getSecondHorizontEclipticSection(thirdEclipticLongitudeTan); 245 | assertEquals(343.0076391971394D, thirdS2); 246 | final boolean thirdReturnDescendent = astrologyUtil.returnDescendent(thirdLocalSiderealDegrees); 247 | assertFalse(thirdReturnDescendent); 248 | 249 | final ZodiacSign thirdSign = astrologyUtil.returnSign(thirdS1, thirdS2, thirdReturnDescendent); 250 | assertEquals(ZodiacSign.Virgo, thirdSign); 251 | final double thirdPosition = astrologyUtil.returnPosition(thirdS1, thirdS2, thirdReturnDescendent); 252 | assertEquals(13.007639197139412D, thirdPosition); 253 | // /////////////////////////////////////////////// 254 | 255 | final Date fourthDate = new Date(1432538100000L); // 2015.05.25 07:15:00 +0000 256 | final double fourthLongitude = -21D; 257 | final double fourthLatitude = -90D; 258 | 259 | final double fourthJd = dateTimeUtil.getJdTimeDate(fourthDate); 260 | assertEquals(2457167.8020833335D, fourthJd); 261 | final double fourthCents = dateTimeUtil.getJulianCenturiesSinceJ2000(fourthJd); 262 | assertEquals(0.1539439310974261D, fourthCents); 263 | final double fourthSiderealDegrees = dateTimeUtil.getSiderealDegrees(fourthJd); 264 | assertEquals(2030031.3106839536D, fourthSiderealDegrees); 265 | final double fourthLocalSiderealDegrees = dateTimeUtil.getLocalSiderealDegrees(fourthSiderealDegrees, fourthLongitude); 266 | assertEquals(330.3106839535758D, fourthLocalSiderealDegrees); 267 | 268 | final double fourthEclipticLongitudeTan = astrologyUtil.calculateEclipticLongitudeJ2000Tangens(fourthLocalSiderealDegrees, fourthLatitude); 269 | assertEquals(1.33728133063789E-16D, fourthEclipticLongitudeTan); // ~0.000000000 270 | 271 | final double fourthS1 = astrologyUtil.getFirstHorizontEclipticSection(fourthEclipticLongitudeTan); 272 | assertEquals(0.0D, fourthS1); 273 | final double fourthS2 = astrologyUtil.getSecondHorizontEclipticSection(fourthEclipticLongitudeTan); 274 | assertEquals(180.0D, fourthS2); 275 | final boolean fourthReturnDescendent = astrologyUtil.returnDescendent(fourthLocalSiderealDegrees); 276 | assertFalse(fourthReturnDescendent); 277 | 278 | final ZodiacSign fourthSign = astrologyUtil.returnSign(fourthS1, fourthS2, fourthReturnDescendent); 279 | assertEquals(ZodiacSign.Aries, fourthSign); 280 | final double fourthPosition = astrologyUtil.returnPosition(fourthS1, fourthS2, fourthReturnDescendent); 281 | assertEquals(0.0D, fourthPosition); 282 | // ///////////////////////////////// 283 | 284 | final Date fifthDate = new Date(1468350780000L); // 2016.07.12 19:13:00 285 | // +0000 286 | final double fifthLongitude = -178D; 287 | final double fifthLatitude = -3D; 288 | 289 | final double fifthJd = dateTimeUtil.getJdTimeDate(fifthDate); 290 | assertEquals(2457582.300694444D, fifthJd); 291 | final double fifthCents = dateTimeUtil.getJulianCenturiesSinceJ2000(fifthJd); 292 | assertEquals(0.1652922845843728D, fifthCents); 293 | final double fifthSiderealDegrees = dateTimeUtil.getSiderealDegrees(fifthJd); 294 | assertEquals(2179659.3601489835D, fifthSiderealDegrees); 295 | final double fifthLocalSiderealDegrees = dateTimeUtil.getLocalSiderealDegrees(fifthSiderealDegrees, fifthLongitude); 296 | assertEquals(41.360148983541876D, fifthLocalSiderealDegrees); 297 | 298 | final double fifthEclipticLongitudeTan = astrologyUtil.calculateEclipticLongitudeJ2000Tangens(fifthLocalSiderealDegrees, fifthLatitude); 299 | assertEquals(-1.2821146345945846D, fifthEclipticLongitudeTan); // ~0.000000000 300 | 301 | final double fifthS1 = astrologyUtil.getFirstHorizontEclipticSection(fifthEclipticLongitudeTan); 302 | assertEquals(127.95285788162039D, fifthS1); 303 | final double fifthS2 = astrologyUtil.getSecondHorizontEclipticSection(fifthEclipticLongitudeTan); 304 | assertEquals(307.9528578816204D, fifthS2); 305 | final boolean fifthReturnDescendent = astrologyUtil.returnDescendent(fifthLocalSiderealDegrees); 306 | assertFalse(fifthReturnDescendent); 307 | 308 | final ZodiacSign fifthSign = astrologyUtil.returnSign(fifthS1, fifthS2, fifthReturnDescendent); 309 | assertEquals(ZodiacSign.Leo, fifthSign); 310 | final double fifthPosition = astrologyUtil.returnPosition(fifthS1, fifthS2, fifthReturnDescendent); 311 | assertEquals(7.952857881620389D, fifthPosition); 312 | } 313 | 314 | /** 315 | * http://de.wikipedia.org/wiki/Aszendent_%28Astrologie%29#Beispiele 316 | * @throws Exception 317 | */ 318 | public final void testTropicalAscendentFull() throws Exception { 319 | //1983.11.10 13:04:00 +0000 320 | assertEquals(ZodiacSign.Pisces, astrologyUtil.determineAscendent(new Date(437317440000L), 16D, 48D).getAscendent()); 321 | //1986.12.10 23:12:00 +0000 322 | assertEquals(ZodiacSign.Gemini, astrologyUtil.determineAscendent(new Date(534640320000L), -27D, -61D).getAscendent()); 323 | //2007.08.07 13:08:00 +0000 324 | assertEquals(ZodiacSign.Libra, astrologyUtil.determineAscendent(new Date(1186492080000L), 17D, 78D).getAscendent()); 325 | //2002.12.16 23:32:00 +0000 326 | assertEquals(ZodiacSign.Pisces, astrologyUtil.determineAscendent(new Date(1040081520000L), 161D, -30D).getAscendent()); 327 | //1987.05.17 18:18:00 +0000 328 | assertEquals(ZodiacSign.Capricorn, astrologyUtil.determineAscendent(new Date(548273880000L), 57D, 17D).getAscendent()); 329 | //1979.09.18 03:35:00 +0000 330 | assertEquals(ZodiacSign.Gemini, astrologyUtil.determineAscendent(new Date(306473700000L), -58D, -1D).getAscendent()); 331 | //1987.09.17 01:24:00 +0000 332 | assertEquals(ZodiacSign.Leo, astrologyUtil.determineAscendent(new Date(558840240000L), -17D, 63D).getAscendent()); 333 | //2020.12.06 00:27:00 +0000 334 | assertEquals(ZodiacSign.Virgo, astrologyUtil.determineAscendent(new Date(1607214420000L), -6D, -14D).getAscendent()); 335 | //1976.10.28 14:19:00 +0000 336 | assertEquals(ZodiacSign.Capricorn, astrologyUtil.determineAscendent(new Date(215360340000L), -61D, -17D).getAscendent()); 337 | //2010.09.03 02:04:00 +0000 338 | assertEquals(ZodiacSign.Leo, astrologyUtil.determineAscendent(new Date(1283479440000L), 51D, -27D).getAscendent()); 339 | //2008.08.03 09:41:00 +0000 340 | assertEquals(ZodiacSign.Cancer, astrologyUtil.determineAscendent(new Date(1217756460000L), -93D, 45D).getAscendent()); 341 | //2015.05.25 07:15:00 +0000 342 | assertEquals(ZodiacSign.Aries, astrologyUtil.determineAscendent(new Date(1432538100000L), -21D, -90D).getAscendent()); 343 | //2016.07.12 19:13:00 +0000 344 | assertEquals(ZodiacSign.Leo, astrologyUtil.determineAscendent(new Date(1468350780000L), -178D, -3D).getAscendent()); 345 | } 346 | 347 | /** 348 | * http://www.sismoloc.info/mc_east_and_ac_north.html 349 | */ 350 | @SuppressWarnings("deprecation") 351 | public final void testMidheavenCalculation() throws Exception { 352 | final Date date = new Date(1471381800000L); // 2016.08.16 21:10:00 +0000 353 | 354 | @SuppressWarnings("unused") 355 | final double latitude = 25D; 356 | final double longitude = 47D; 357 | 358 | final double jd = dateTimeUtil.getJdTimeDate(date); 359 | assertEquals(2457617.3819444445D, jd); 360 | final double cents = dateTimeUtil.getJulianCenturiesSinceJ2000(jd); 361 | assertEquals(0.16625275686364124D, cents); 362 | final double siderealDegrees = dateTimeUtil.getSiderealDegrees(jd); 363 | assertEquals(2192323.187890825D, siderealDegrees); 364 | final double localSiderealDegrees = dateTimeUtil.getLocalSiderealDegrees(siderealDegrees, longitude); 365 | assertEquals(330.1878908248618D, localSiderealDegrees); 366 | final double midheaven = astrologyUtil.calculateMidheaven(localSiderealDegrees); 367 | assertEquals(328.01438873794672D, midheaven); 368 | final double midheavenWat = astrologyUtil.calculateMc(localSiderealDegrees); 369 | assertEquals(238.01438873794672D, midheavenWat); 370 | 371 | /****/ 372 | final double armc = 329.8785D; 373 | final double mc = astrologyUtil.calculateMidheaven(armc); 374 | assertEquals(327.69227778042836D, mc); 375 | /****/ 376 | 377 | final Date watDate = new Date(946708034000L); // 2000.01.01 06:27:14 378 | // +0000 379 | final double watHours = dateTimeUtil.getDecimalHours(watDate); 380 | assertEquals(6.453888888888889D, watHours); 381 | final double watDegrees = dateTimeUtil.convertHoursToDegree(watHours); 382 | assertEquals(96.80833333333334D, watDegrees); 383 | final double watMc = astrologyUtil.calculateMc(watDegrees); 384 | assertEquals(186.25116872097536D, watMc); 385 | } 386 | 387 | @SuppressWarnings("deprecation") 388 | public final void testObliqueAscensionCalculation() throws Exception { 389 | final double longitude = 16D; 390 | final AscendentAndOffset aao = astrologyUtil.determineAscendent(new Date(437317440000L), longitude, 48D); // 1983.11.10 13:04:00 +0000 391 | @SuppressWarnings("unused") 392 | final double oa = astrologyUtil.calculateObliqueAscension(aao.getAscendent().getEclipticLongitude() + aao.getOffset(), longitude); 393 | } 394 | 395 | public final void testDegreeConversion() throws Exception { 396 | assertEquals("0" + Constants.DEGREE_SIGN + "0" + Constants.MINUTE_SIGN + "0.0" + Constants.SECOND_SIGN, astrologyUtil.convertDegrees(0.0D)); 397 | final double firstInput = 42.2305370D; 398 | assertEquals("42" + Constants.DEGREE_SIGN + "13" + Constants.MINUTE_SIGN + "49.9" + Constants.SECOND_SIGN, astrologyUtil.convertDegrees(firstInput)); 399 | final double secondInput = -83.7466403; 400 | assertEquals("-83" + Constants.DEGREE_SIGN + "44" + Constants.MINUTE_SIGN + "47.9" + Constants.SECOND_SIGN, astrologyUtil.convertDegrees(secondInput)); 401 | } 402 | 403 | public final void testTrigonometry() throws Exception { 404 | final double x = 0.111D; 405 | final double sinX = Math.sin(x); 406 | final double cosX = Math.cos(x); 407 | assertEquals(NumberFormat.getFormat("#.0000").format(x), NumberFormat.getFormat("#.0000").format(Math.asin(sinX))); 408 | assertEquals(NumberFormat.getFormat("#.0000").format(x), NumberFormat.getFormat("#.0000").format(Math.acos(cosX))); 409 | } 410 | 411 | @Override 412 | public final String getModuleName() { 413 | return "astrochart.AstroChart"; 414 | } 415 | } 416 | -------------------------------------------------------------------------------- /test/astrochart/client/DateTimeUtilTester.java: -------------------------------------------------------------------------------- 1 | package astrochart.client; 2 | 3 | 4 | import java.util.Date; 5 | import astrochart.client.util.Constants; 6 | import astrochart.client.util.DateTimeUtil; 7 | import com.google.gwt.i18n.client.NumberFormat; 8 | import com.google.gwt.junit.client.GWTTestCase; 9 | 10 | 11 | public class DateTimeUtilTester extends GWTTestCase { 12 | private DateTimeUtil dateTimeUtil; 13 | 14 | static final long SIXTH_OF_AUGUST_2006 = 1154844000000L; //2006.08.06 06:00:00 +0000 = 08:00:00 MESZ 15 | static final double JD_SIXTH_OF_AUGUST_2006 = 2453953.75D; //JD for 2006.08.06 06:00:00 +0000 16 | 17 | static final long FIRST_OF_JANUARY_2004 = 1072915200000L; //2004.01.01 00:00:00 +0000 18 | static final String FIRST_OF_JANUARY_2004_SD = "2004.01.01 06:39:58"; 19 | static final String FIRST_OF_JANUARY_2004_SD_WAT = "2004.01.01 06:39:59"; 20 | 21 | static final long FIRST_OF_JANUARY_2001_MIDDAY = 946728000000L; 22 | 23 | public final void gwtSetUp() throws Exception { 24 | dateTimeUtil = new DateTimeUtil(); 25 | } 26 | 27 | public final void testJdDate() throws Exception { 28 | final Date date = new Date(); 29 | date.setTime(SIXTH_OF_AUGUST_2006); 30 | assertEquals(JD_SIXTH_OF_AUGUST_2006, dateTimeUtil.getJdTimeDate(date)); 31 | } 32 | 33 | public final void testSidDate() throws Exception { 34 | final Date date = new Date(); 35 | date.setTime(FIRST_OF_JANUARY_2004); 36 | final Date lst = dateTimeUtil.getLocalSidTimeDate(date); 37 | assertEquals(FIRST_OF_JANUARY_2004_SD_WAT, dateTimeUtil.formatLocalDate(lst)); 38 | // assertEquals(FIRST_OF_JANUARY_2004_SD, 39 | // dateTimeUtil.formatLocalDate(lst)); 40 | } 41 | 42 | public final void testJdn() throws Exception { 43 | final Date date = new Date(); 44 | date.setTime(SIXTH_OF_AUGUST_2006); 45 | final double jdn = dateTimeUtil.getJulianDayNumber(date); 46 | assertEquals(2453954.0D, jdn); 47 | final double jdo = dateTimeUtil.getJulianDayNumberTimeDropped(date); 48 | assertEquals(2453953.5D, jdo); 49 | } 50 | 51 | /** 52 | * Does not compute! 53 | * @throws Exception 54 | */ 55 | public final void testGmstSidereal() throws Exception { 56 | final double jd = 2456038.9600D; 57 | 58 | 59 | final double gmstSiderealSeconds = dateTimeUtil.getGmstSeconds(jd); 60 | System.out.println("gmstSiderealSeconds: " + gmstSiderealSeconds); 61 | final double starTimeHours = (gmstSiderealSeconds / Constants.SECONDS_PER_HOUR); 62 | System.out.println("starTimeHours: " + starTimeHours); 63 | final double gmstSiderealDegrees2 = dateTimeUtil.convertHoursToDegree(starTimeHours); 64 | System.out.println("gmstSiderealDegrees2: " + gmstSiderealDegrees2); 65 | System.out.println("gmstSiderealDegrees2: " + gmstSiderealDegrees2 % Constants.DEGREES_IN_CIRCLE); 66 | 67 | final double gmstHours = dateTimeUtil.getGmstHours(jd); 68 | System.out.println("gmstHours: " + gmstHours); 69 | System.out.println("gmstDeg: " + gmstHours * Constants.DEGREES_PER_HOUR); 70 | 71 | 72 | final double gmstSiderealHours = dateTimeUtil.getSiderealHours(jd); 73 | final double gmstSiderealDegrees = dateTimeUtil.getSiderealDegrees(jd); 74 | final NumberFormat nf = NumberFormat.getFormat("0.00000"); 75 | assertEquals(nf.format(gmstSiderealDegrees), nf.format(gmstSiderealHours * Constants.DEGREES_PER_HOUR)); 76 | System.out.println("gmstSiderealDegrees: " + nf.format(gmstSiderealDegrees)); 77 | System.out.println("gmstSiderealDegrees: " + gmstSiderealDegrees % Constants.DEGREES_IN_CIRCLE); 78 | } 79 | 80 | public final void testJulianCenturies() throws Exception { 81 | // final long jdn = 2453954L; 82 | // final double jCent = dateTimeUtil.calculateJulianCenturies(jdn); 83 | // assertEquals(2451545L, jCent); 84 | } 85 | 86 | /* 87 | final Date wat = new Date(); 88 | wat.setTime(0L); 89 | wat.setYear(2006 - 1900); 90 | wat.setMonth(7); 91 | wat.setDate(6); 92 | wat.setHours(8); 93 | wat.setMinutes(0); 94 | wat.setSeconds(0); 95 | System.out.println("wat: " + dateTimeUtil.formatDateAsUtc(wat)); 96 | System.out.println("wat: " + DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss Z").format(wat, TimeZone.createTimeZone(0))); 97 | System.out.println("ms: " + wat.getTime()); 98 | */ 99 | 100 | @Override 101 | public final String getModuleName() { 102 | return "astrochart.AstroChart"; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /war/AstroChart.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 2em; 3 | font-weight: bold; 4 | color: #777777; 5 | margin: 40px 0px 70px; 6 | text-align: center; 7 | } 8 | 9 | .sendButton { 10 | display: block; 11 | font-size: 16pt; 12 | } 13 | 14 | .gwt-DialogBox { 15 | width: 400px; 16 | } 17 | 18 | .dialogVPanel { 19 | margin: 5px; 20 | } 21 | 22 | .serverResponseLabelError { 23 | color: red; 24 | } 25 | 26 | #closeButton { 27 | margin: 15px 6px 6px; 28 | } 29 | 30 | div#page { 31 | background: #FFFFFF; 32 | width: 1024px; 33 | height: 768px; 34 | margin: 0 auto; 35 | } 36 | 37 | div#title { 38 | background: #CCCCCC; 39 | } 40 | -------------------------------------------------------------------------------- /war/AstroChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Astrology Chart Generator 7 | 8 | 9 | 10 | 11 | 16 |
17 |
18 |
19 | 20 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /war/WEB-INF/.gitignore: -------------------------------------------------------------------------------- 1 | /appengine-generated 2 | 3 | /classes 4 | 5 | /deploy 6 | 7 | -------------------------------------------------------------------------------- /war/WEB-INF/appengine-web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | astro-chart 4 | 1 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /war/WEB-INF/lib/.gitignore: -------------------------------------------------------------------------------- 1 | /appengine-api-1.0-sdk-1.8.1.1.jar 2 | /appengine-api-labs.jar 3 | /appengine-endpoints.jar 4 | /appengine-jsr107cache-1.8.1.1.jar 5 | /datanucleus-appengine-1.0.10.final.jar 6 | /datanucleus-core-1.1.5.jar 7 | /datanucleus-jpa-1.1.5.jar 8 | /geronimo-jpa_3.0_spec-1.1.1.jar 9 | /geronimo-jta_1.1_spec-1.1.1.jar 10 | /gson-2.1.jar 11 | /gwt-servlet.jar 12 | /jdo2-api-2.3-eb.jar 13 | /jsr107cache-1.1.jar 14 | -------------------------------------------------------------------------------- /war/WEB-INF/logging.properties: -------------------------------------------------------------------------------- 1 | # add to appengine-web.xml: 2 | # 3 | # 4 | # 5 | .level = WARNING 6 | -------------------------------------------------------------------------------- /war/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | adminService 11 | astrochart.server.service.AdminServiceImpl 12 | 13 | 14 | epochService 15 | astrochart.server.service.EpochServiceImpl 16 | 17 | 18 | geocodeService 19 | astrochart.server.service.GeocodeServiceImpl 20 | 21 | 22 | adminService 23 | /astrochart/admin 24 | 25 | 26 | epochService 27 | /astrochart/epoch 28 | 29 | 30 | geocodeService 31 | /astrochart/geocode 32 | 33 | 34 | 35 | 36 | AstroChart.html 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /war/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tok/AstroChart/c7f7702325e46f2207c1b06f83e4d1ddc418f971/war/favicon.ico -------------------------------------------------------------------------------- /war/images/AstroChartTitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tok/AstroChart/c7f7702325e46f2207c1b06f83e4d1ddc418f971/war/images/AstroChartTitle.png --------------------------------------------------------------------------------