/**
*
* Panchang.java
*
* Created on February 24, 2003, 11:54 AM
*
* @author E. Rajasekar
*
*/
package app.astrosoft.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import app.astrosoft.beans.ChartData;
import app.astrosoft.beans.Place;
import app.astrosoft.beans.PlanetChartData;
import app.astrosoft.beans.PlanetaryInfo;
import app.astrosoft.consts.AstroConsts;
import app.astrosoft.consts.AstrosoftTableColumn;
import app.astrosoft.consts.Ayanamsa;
import app.astrosoft.consts.DisplayConsts;
import app.astrosoft.consts.DisplayStrings;
import app.astrosoft.consts.Karana;
import app.astrosoft.consts.Nakshathra;
import app.astrosoft.consts.Paksha;
import app.astrosoft.consts.Planet;
import app.astrosoft.consts.Rasi;
import app.astrosoft.consts.Thithi;
import app.astrosoft.consts.Varga;
import app.astrosoft.consts.WeekDay;
import app.astrosoft.consts.Yoga;
import app.astrosoft.export.Exportable;
import app.astrosoft.export.Exporter;
import app.astrosoft.pref.AstrosoftPref;
import app.astrosoft.ui.AstroSoft;
import app.astrosoft.ui.table.DefaultColumnMetaData;
import app.astrosoft.ui.table.DefaultTable;
import app.astrosoft.ui.table.MapTableRow;
import app.astrosoft.ui.table.MapTableRowHelper;
import app.astrosoft.ui.table.Table;
import app.astrosoft.ui.table.TableData;
import app.astrosoft.ui.table.TableDataFactory;
import app.astrosoft.util.AstroUtil;
import app.astrosoft.util.Mod;
import app.astrosoft.util.SwissHelper;
import app.astrosoft.util.TransitHelper;
import swisseph.*;
public class Panchang {
private static final AstrosoftPref preferences = AstroSoft.getPreferences();
private static final double PAN_APPROXIMATION = 0.01;
private SwissHelper swissHelper;
private Place place;
private double moon;
private double sun;
private double totalSpeed;
private double diffSpeed;
private Calendar cal;
private WeekDay weekday;
private double sunrise;
private double sunset;
private double panTime;
private double timeZone;
private PanEvent nakshathra;
private PanEvent thithi;
private PanEvent yoga;
private KaranaEvent karana;
private Paksha pak;
private EnumMap<Planet, Integer> rasi;
private EnumMap<Planet, Boolean> dir;
private static DefaultColumnMetaData panchangColumnMetaData;
public static final int AUS_TIME_ROW = 9;
/** Creates a new instance of Panchang */
public Panchang(Calendar cal ) {
this.cal = AstroUtil.getCalendar(cal.getTime());
calcPanchang();
}
public Panchang(Date date) {
cal = AstroUtil.getCalendar(date);
calcPanchang();
}
/*public void setAyanamsa( Ayanamsa ayanamsa ) {
sw.swe_set_sid_mode( ayanamsa.ayaValue(), 0.0, 0.0 );
calcPanchang( );
}
private void setPanCalcTime(double time) {
refTime = time;
panTime = refTime - this.timeZone; // For 12.00 A.M
calcPanchang();
}*/
private void calcPlanetaryInfo( ) {
place = preferences.getPlace();
timeZone = ((double)cal.getTimeZone().getRawOffset() / AstroConsts.MILLIS_IN_HR) + (cal.get(Calendar.DST_OFFSET) / AstroConsts.MILLIS_IN_HR) ;
place.setTimeZone(timeZone);
panTime = preferences.getPanCalcTime() - timeZone;
//System.out.println("TZ " + timeZone);
swissHelper = new SwissHelper(new SweDate( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), panTime ));
EnumMap<Planet, Double> planetPosition = swissHelper.getPlanetaryPosition();
sun = planetPosition.get(Planet.Sun);
moon = planetPosition.get(Planet.Moon);
rasi = PlanetaryInfo.positionToRasiNum(planetPosition);
rasi.put(Planet.Ascendant, swissHelper.getAscendant(place.longitude(), place.latitude()).ordinal() + 1);
dir = swissHelper.getPlanetDirection();
double moonSpeed = swissHelper.getPlanetSpeed(Planet.Moon);
double sunSpeed = swissHelper.getPlanetSpeed(Planet.Sun);
totalSpeed = sunSpeed + moonSpeed;
diffSpeed = moonSpeed - sunSpeed;
}
private void calcPanchang( ) {
calcPlanetaryInfo( );
TransitHelper transitHelper = swissHelper.getTransitHelper(Planet.Moon);
Date nakEndDate = transitHelper.getTransitDate(AstroUtil.nakEndPosition(moon), swissHelper.getSweDate().getJulDay());
double nakEndTime = AstroUtil.dateToTimeDouble(nakEndDate);
if (((nakEndDate.getTime() - cal.getTimeInMillis()) / AstroConsts.MILLIS_IN_DAY) > 1){
nakEndTime = nakEndTime + 24.00;
}
nakshathra = new PanEvent(Nakshathra.ofDeg(moon).toString(), nakEndTime);
thithi = new PanEvent(Thithi.ofDeg( sun, moon ).toString(), findThithiEnd( sun, moon, diffSpeed ));
yoga = new PanEvent(Yoga.ofDeg( sun , moon ).toString(), findYogaEnd( ( sun + moon ) % 360, totalSpeed ));
karana = calcKarana();
pak = Paksha.ofDeg( sun, moon );
weekday = WeekDay.ofCalendar( cal );
sunrise = AstroUtil.getSunRise( cal, place );
sunset = AstroUtil.getSunSet( cal, place );
}
private KaranaEvent calcKarana() {
KaranaEvent karanaEvent;
Karana[] karanas = Karana.ofDeg(sun, moon);
double position = getMoonSunDiff(sun, moon);
double time = 0;
double firstTime = 0;
double secondTime = 0;
double firstBal = AstroConsts.karanaLength - ( position % AstroConsts.karanaLength );
double expected = (position + firstBal) % 180;
//System.out.println("Firstbal " + firstBal );
//System.out.println("expected " + expected );
if (expected % AstroConsts.thithiLength == 0){
firstTime = thithi.getEnding();
double secondBal = firstBal + AstroConsts.karanaLength;
time = AstroUtil.endTime( diffSpeed, secondBal );
secondTime = time + timeZone + computeCorrection(position + AstroConsts.karanaLength, expected + AstroConsts.karanaLength, time, AstroConsts.karanaLength);
}else {
time = AstroUtil.endTime( diffSpeed, firstBal );
firstTime = time + timeZone + computeCorrection(position, expected, time, AstroConsts.karanaLength);
secondTime = thithi.getEnding();
}
karanaEvent = new KaranaEvent(karanas[0].toString(),firstTime, karanas[1].toString(), secondTime );
return karanaEvent;
}
private double findYogaEnd( double position, double speed ) {
double bal = AstroConsts.yogaLength - ( position % AstroConsts.yogaLength );
double time = AstroUtil.endTime( speed, bal );
return time + timeZone + yogaCorrection(position, position + bal, time);
}
private double yogaCorrection(double position, double expected, double caltime){
double correction = 0.0;
SwissHelper swissHelper = new SwissHelper(new SweDate( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), caltime));
EnumMap<Planet, Double> planetPosition = swissHelper.getPlanetaryPosition(EnumSet.of(Planet.Sun, Planet.Moon));
double newmoon = planetPosition.get(Planet.Moon);
double newsun = planetPosition.get(Planet.Sun);
double newposition = (newsun + newmoon) % 360;
/*if (newposition > 360.00){
newposition = 360.00 - newposition;
}*/
double bal = expected - newposition;
if (bal > AstroConsts.yogaLength){
bal = 360 - bal;
}
/*System.out.println("Old Pos" + position);
System.out.println("Exp Pos" + expected);
System.out.println("Bal " + bal);
System.out.println("New Pos" + newposition + "\n");*/
correction = AstroUtil.endTime(totalSpeed, bal);
if (Math.abs(bal) > PAN_APPROXIMATION) {
correction = correction + yogaCorrection(newposition, expected, caltime + correction);
}
return correction;
}
private double findThithiEnd( double sun, double moon, double speed ) {
double diff = getMoonSunDiff(sun, moon);
double bal = AstroConsts.thithiLength - ( diff % AstroConsts.thithiLength );
double time = AstroUtil.endTime( diffSpeed, bal );
//System.out.println(sun + " - " + moon + " - " + time + " - " + speed);
return (timeZone + time + computeCorrection(getMoonSunDiff(sun, moon), diff + bal, time, AstroConsts.thithiLength));
}
private double computeCorrection(double position, double expected, double caltime, double length ) {
double correction = 0.0;
SwissHelper swissHelper = new SwissHelper(new SweDate( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), caltime));
EnumMap<Planet, Double> planetPosition = swissHelper.getPlanetaryPosition(EnumSet.of(Planet.Sun, Planet.Moon));
double newmoon = planetPosition.get(Planet.Moon);
double newsun = planetPosition.get(Planet.Sun);
double newdiff = getMoonSunDiff(newsun, newmoon);
/*System.out.println(
"Old Pos " + position + "New Diff " + newdiff
+ AstroUtil.dms( newsun ) + " - " + AstroUtil.dms( newmoon ) );*/
double newbal = expected - newdiff;
//System.out.println("pos " + position + " newdiff " + newdiff + " new bal " + newbal);
if ( (expected % 180) == 0 && newbal > length ) {
newbal = newbal - 180;
//System.out.println("new bal > " + newbal);
}
correction = AstroUtil.endTime( diffSpeed, newbal );
/*System.out.println(
"Correction : " + correction + " Bal: " + newbal + " Expected : "
+ expected );*/
if (Math.abs(newbal) > PAN_APPROXIMATION){
correction = correction + computeCorrection(getMoonSunDiff(newsun, newmoon), expected , caltime + correction, length);
}
return correction;
}
/*public void preferenceChange(PreferenceChangeEvent evt) {
if(evt.getKey().equals(AstrosoftPref.Preference.Ayanamsa.name())){
setAyanamsa(Enum.valueOf(Ayanamsa.class, evt.getNewValue()));
}else if (evt.getKey().equals(AstrosoftPref.Preference.PanCalcTime.name())){
setPanCalcTime(Double.parseDouble(evt.getNewValue()));
}
}*/
public String rahuKala(){
return weekday.rahuKala();
}
public String yamaKanda(){
return weekday.yamaKanda();
}
public String[] auspiciousTime(){
return weekday.auspiciousTime();
}
public Calendar getDate() {
return cal;
};
private static DefaultColumnMetaData getPanchangColumnMetaData() {
if (panchangColumnMetaData == null){
panchangColumnMetaData = new DefaultColumnMetaData(AstrosoftTableColumn.keyvalCols());
panchangColumnMetaData.localizeColumns();
}
return panchangColumnMetaData;
}
public TableData<MapTableRow> getPanchangTableData() {
List<MapTableRow> rows = new ArrayList<MapTableRow>();
MapTableRowHelper helper = new MapTableRowHelper(getPanchangColumnMetaData());
rows.add(helper.createRow(DisplayStrings.DATE_STR, AstroUtil.formatDate(cal.getTime())));
rows.add(helper.createRow(DisplayStrings.DAY_STR, weekday));
rows.add(helper.createRow(DisplayStrings.NAK_STR + " ( " + AstrosoftTableColumn.End.toString() + " ) ", nakshathra));
rows.add(helper.createRow(DisplayStrings.THITHI_STR + " ( " + AstrosoftTableColumn.End.toString() + " ) ", thithi));
rows.add(helper.createRow(DisplayStrings.PAKSHA_STR, pak));
rows.add(helper.createRow(DisplayStrings.YOGA_STR + " ( " + AstrosoftTableColumn.End.toString() + " ) ", yoga));
rows.add(helper.createRow(DisplayStrings.KARANA_STR + " ( " + AstrosoftTableColumn.End.toString() + " ) ", karana));
rows.add(helper.createRow(DisplayStrings.SUNRISE_STR, AstroUtil.timeFormat(sunrise)));
rows.add(helper.createRow(DisplayStrings.SUNSET_STR, AstroUtil.timeFormat(sunset)));
String auspiciousTime = Arrays.toString(auspiciousTime());
rows.add(helper.createRow(DisplayStrings.AUS_TIME_STR, auspiciousTime.substring(1, auspiciousTime.length() - 1)));
rows.add(helper.createRow(DisplayStrings.RAHU_KALA_STR, rahuKala()));
rows.add(helper.createRow(DisplayStrings.YAMA_KANDA_STR, yamaKanda()));
return TableDataFactory.getTableData(rows);
}
public Table getPanchangTable() {
return new DefaultTable(getPanchangTableData(), getPanchangColumnMetaData());
}
public ChartData getPlanetChartData(){
return new PlanetChartData(Varga.Rasi, rasi, dir);
}
public static double getMoonSunDiff(double sun, double moon){
double diff;
if ( moon > sun ) {
diff = moon - sun;
} else {
diff = ( moon + 360 ) - sun;
}
if ( diff > 180.0 ) {
diff = diff - 180;
}
return diff;
}
public WeekDay getWeekday() {
return weekday;
}
public static void main( String[] args ) {
for(int i = 1; i <= 30 ; i++){
Panchang pan = new Panchang( new GregorianCalendar(2006, 9, i, 0, 0));
System.out.println(pan);
}
// FIXME ArrayOutOfBounds Exception if uncomment
// System.out.println(DisplayConsts.weekDays[0][pan.weekday] + " Paksha " + DisplayConsts.pakshaNames[0][pan.pak] + " Thithi no " + (pan.thithi+1) + " " + DisplayConsts.thithiNames[pan.thithi] + " Ends " + AstroUtil.panFormat(pan.thithiEnd, refTime, AstroSoft.ENGLISH) + " " + pan.thithiEnd + " SunRise/Set" + AstroUtil.timeFormat(pan.sunrise)+"/"+AstroUtil.timeFormat(pan.sunset) );
// System.out.println(DisplayConsts.yogaNames[pan.yoga] + " Yoga Ends " + AstroUtil.panFormat(pan.yogaEnd, refTime, AstroSoft.ENGLISH) );
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.cal.getTime() + "\n");
sb.append(this.weekday + "\n");
sb.append(this.nakshathra + "\n");
sb.append(this.thithi + "\n");
sb.append(this.pak + "\n");
sb.append(this.yoga + "\n");
sb.append(this.karana + "\n");
sb.append(AstroUtil.timeFormat(this.sunrise) + " - " + AstroUtil.timeFormat(this.sunset) + "\n");
return sb.toString();
}
private static class PanEvent{
private String event;
private double ending;
public PanEvent(String event, double ending){
this.event = event;
this.ending = ending;
}
public double getEnding() {
return ending;
}
public String toString(){
return event + " ( " + AstroUtil.todegmin(ending, ":") + " ) ";
}
}
private static class KaranaEvent {
private PanEvent first;
private PanEvent second;
public KaranaEvent(String first, double firstEnding, String second, double secondEnding){
this.first = new PanEvent(first, firstEnding);
this.second = new PanEvent(second, secondEnding);
}
public String toString() {
return first + " , " + second;
}
}
}