<commit_before>// satchat Copyright 2014 
// <NAME> KI6CQ - Economic and Financial Technology Consulting LLC - www.eaftc.com
//
// <your name could be here too> if you contribute code features or patches we use
//
// Open Source License: MIT License -- see http://opensource.org/licenses/MIT
// 
// satchat is a MeteorJS based chat room that also displays satellite tracking data
//
// The chats and about 24hrs of 1 minute satellite tracking data are kept in a MongoDB database
// Calculations for tracking must be supplied to the database externally
//
// This file: world.js began as a modification of Baranovskiy's demo used on the Raphael js library website
// As of Nov.8, most of the demo code is gone and this is mostly sat display code
// <NAME> 8 Nov 2014 
// 
//

var _depTLE = new Deps.Dependency();

var updatePLibTLEs = function(){
  try {
    _depTLE.changed();
    PLib.tleData = TLE.findOne().tleData;
    PLib.InitializeData(); 
  } catch(e) {
    console.log("error in app.js updatePLibTLEs:",e)
  }
};

Track = new Mongo.Collection("track");
Messages = new Mongo.Collection("messages");
QTH = new Mongo.Collection("qth");
TLE = new Mongo.Collection("tle");
Meteor.subscribe("track");
Meteor.subscribe("messages");
Meteor.subscribe("qth");
Meteor.subscribe("tle", updatePLibTLEs);
Meteor.subscribe("userPresence");  


satmag = 1.0;
  
qthxy = {};
myQTH = new LatLon(0,0);

Session.set('ignore',[]);

var utcHMS = function(t){
  d = new Date(t);
  day = d.getUTCDate(t);
  h = d.getUTCHours();
  m = d.getUTCMinutes();
  if (h<10) h='0'+h;
  if (m<10) m='0'+m;
  return day+' '+h+':'+m;
};


whoIs = function(uid){
  var found =  Meteor.users.findOne(uid);
  if (found) found = found.username;
  return found;
};

ignored = function(call){
  if (!Session.get('ignore')) return false;
  return (Session.get('ignore').indexOf(call)>=0);
}

checkedIn = function(){
  var everyone =  Presences.find().fetch();
  var calls = [];
  var call;
  for(var i=0,l=everyone.length;i<l;++i){
      if ((everyone[i].state) && (everyone[i].userId)){
        call = whoIs(everyone[i].userId);
        if (!ignored(call)) calls.push(call);
      }
  }
  return calls.sort();
};

lastMessages = function(msgCursor, order){
    var last = {}, lastmsgs = [],call='';
    var msgs = msgCursor.fetch();
    for(var i=0,l=msgs.length;i<l;++i){
      call = msgs[i].call;
      if (last[call]){
        if (msgs[i].t>last[call].t){
          last[call] = msgs[i];
        }
      } else {
        last[call] = msgs[i];
      }
    }
    for (k in last){
      if (last.hasOwnProperty(k)) lastmsgs.push(last[k]);
    }
  if (order) lastmsgs.sort(order);
  return lastmsgs;
};

orderBy = function(field, m){
  return function(a,b){
    if (a[field]>b[field]) return m;
    if (a[field]<b[field]) return -m;
    return 0;
  }
};

var PleaseSignIn = function(){
  $( "#dialog-psi" ).dialog({
      modal: true,
      buttons: {
        Ok: function() {
          $( this ).dialog( "close" );
        }
      }
  });
};

var registerHelpers = function(obj){
  for(var k in obj){
    if (obj.hasOwnProperty(k)){
      if (typeof(obj[k])==='function'){
        Template.registerHelper(k, obj[k]);
      }
    }
  }
};

registerHelpers({
  screenHeight: function(){
    return sceeen.height;
  },
  screenWidth: function(){
    return screen.width;
  },
  windowHeight: function(){
    return $(window).height();
  },
  windowWidth: function(){
    return $(window).width();
  },
  msgs: function(){ 
    var query = {call: {$nin: Session.get('ignore')}};
    return Messages.find(query);
  },
  announcements: function(){
    var query = {$and: [{call: {$nin: Session.get('ignore')}},
                        {t: {$gt: (+new Date() - 2*86400000)}},
                                 {txt: {$in: [/^!/]}}
                                ]};
    var msgs =  Messages.find(query);
    return lastMessages(msgs, orderBy('call'));
  },
  lastTransmission: function(){
    var query = {call: {$nin: Session.get('ignore')}};
    return lastMessages(Messages.find(query), orderBy('time', -1));
  },
  checkedIn: function(){
    return checkedIn();
  },
  hms: utcHMS
});

Template.passTable.helpers({
  passes: function(){
    var listOfPasses = PLib.getTodaysPasses();
    listOfPasses.sort(function(a,b){
      return a.dateTimeStart-b.dateTimeStart;
    });
    _depTLE.depend();
    // thanks  http://stackoverflow.com/a/18216255/103081 for how to define explicit dependencies
    return listOfPasses;
  }
})

Template.app.events({
  'keyup #ignore': function(event, template){
    Session.set('ignore',$('#ignore').val().replace(/\n/g,' ').split(/[ ,]+/));
  },
 'click .signout': function(event, template){
    if (confirm("thanks 73 was good qso - GO QRT?")){
        Meteor.logout();
        $('.signinEnabled').prop('disabled', true);
        Session.set('callsign','');
    }
  },
  'click .signin': function(event, template){
      var callsign = $('#callsign').val();
      if ((typeof(callsign)==="string") && (callsign.length>2)){
        callsign = callsign.toUpperCase();
        $('#callsign').val(callsign);
        Session.set('callsign',callsign);
        var pass = $('#pass').val();
        var onGoodPassword = function(){
            console.log('good password');
            Meteor.call('chatRegister', callsign, qthxy);
            $('.signinEnabled').prop('disabled',false);          
        };
        Meteor.loginWithPassword(callsign, $('#pass').val(), function(e){
          if (e){
            // if bad password -- do nothing
            if (/password/.test(e.reason)) return false;
            if (/not found/.test(e.reason)){
              if (confirm("[create account] Check callsign for errors. You entered:  "+callsign)){
                Accounts.createUser({'username': callsign, 
                                     'password': <PASSWORD>}, 
                                    function(e){
                                      if (e){
                                        $('#signinWarning').text('bad callsign or password');
                                      } else {
                                        console.log('created user');
                                        onGoodPassword();
                                      }
                                    });

              }
            }
          } else {    
            onGoodPassword();
          }
        });
      }
  },
  'keyup #compose': function(){
    if (!Meteor.userId()){
      // not logged in
      PleaseSignIn();
    } else {
      if ( ($('#compose').val().length>2) && (/\n$/.test($('#compose').val()))  ) {
        $('#send').prop('disabled', true);
        Meteor.call('sendMessage', $('#compose').val() );
        $('#compose').val('');
        setTimeout(function(){
          $('#send').prop('disabled', false);
        }, 1000);      
      }
    }
  },
  'click #satbigger': function(){
    satmag = satmag * 1.5;
  },
  'click #satsmaller': function(){
    satmag = satmag/1.5;
  }
}); 

Template.app.rendered = function(){
  $('#chatBody').tabs();
  if (($.browser) && (!$.browser.mobile)){
    // desktop only
    $('#chatBody').draggable().resizable();    
  }
  Template.app.firstscrollqso = 1;
  $('.firstscrollqso').click(function(){
      if (Template.app.firstscrollqso) scrollToEnd($('#qso .vscroll'));
      Template.app.firstscrollqso = 0;
  });
};

// see http://stackoverflow.com/a/11551414/103081 for scroll to bottom

scrollToEnd = function(j){
  if (j && j.scrollTop) j.scrollTop(j.prop('scrollHeight'));
};

Template.msg.rendered = function(){
    // select the parent of the paragraph elements and scoll to end if scrollable
    var chatDiv = this.$('p').parent('.vscroll'); 
    scrollToEnd(chatDiv);
};

makeWorld = function (){
  var r = Raphael(0, 0, 600, 300);
  world = r.image("/nasa-world-dec.jpg",0,0,600,300);
  world.getXY = function (lat, lon) {
    return {
      cx: lon * (300.0/180.0) + 300.0,
      cy: lat * (-150.0/90.0) + 150.0
    };
  };
  world.getLatLon = function (x, y) {
    return {
      lat: (y - 150.0) / -(90.0/150.0),
      lon: (x - 300.0) / (180.0/300.0)
    };
  };

  try {
    navigator.geolocation && navigator.geolocation.getCurrentPosition(
      function (pos) {
        qthxy = world.getXY(pos.coords.latitude, pos.coords.longitude);
        myQTH = new LatLon(pos.coords.latitude, pos.coords.longitude);
        if (PLib && PLib.configureGroundStation) {
          PLib.configureGroundStation(pos.coords.latitude, pos.coords.longitude);
          _depTLE.changed();
        }
      });
  } catch (e) {}

  return {
    'r': r,
    'world': world
  }
};


satTrack = {};

var TrackUpdater = function(){
  Tracker.autorun(function(){
    console.log("fetching satellite tracks");
    var now = Math.floor((+new Date()/1000.0));
    var tracks = Track.find({'end': {$gt: now}}).fetch();<commit_msg>change dependency name from _depTLE to _depSat cosmetic change only<commit_after>// satchat Copyright 2014 
// <NAME> KI6CQ - Economic and Financial Technology Consulting LLC - www.eaftc.com
//
// <your name could be here too> if you contribute code features or patches we use
//
// Open Source License: MIT License -- see http://opensource.org/licenses/MIT
// 
// satchat is a MeteorJS based chat room that also displays satellite tracking data
//
// The chats and about 24hrs of 1 minute satellite tracking data are kept in a MongoDB database
// Calculations for tracking must be supplied to the database externally
//
// This file: world.js began as a modification of Baranovskiy's demo used on the Raphael js library website
// As of Nov.8, most of the demo code is gone and this is mostly sat display code
// <NAME> 8 Nov 2014 
// 
//

var _depSat = new Deps.Dependency();

var updatePLibTLEs = function(){
  try {
    _depSat.changed();
    PLib.tleData = TLE.findOne().tleData;
    PLib.InitializeData(); 
  } catch(e) {
    console.log("error in app.js updatePLibTLEs:",e)
  }
};

Track = new Mongo.Collection("track");
Messages = new Mongo.Collection("messages");
QTH = new Mongo.Collection("qth");
TLE = new Mongo.Collection("tle");
Meteor.subscribe("track");
Meteor.subscribe("messages");
Meteor.subscribe("qth");
Meteor.subscribe("tle", updatePLibTLEs);
Meteor.subscribe("userPresence");  


satmag = 1.0;
  
qthxy = {};
myQTH = new LatLon(0,0);

Session.set('ignore',[]);

var utcHMS = function(t){
  d = new Date(t);
  day = d.getUTCDate(t);
  h = d.getUTCHours();
  m = d.getUTCMinutes();
  if (h<10) h='0'+h;
  if (m<10) m='0'+m;
  return day+' '+h+':'+m;
};


whoIs = function(uid){
  var found =  Meteor.users.findOne(uid);
  if (found) found = found.username;
  return found;
};

ignored = function(call){
  if (!Session.get('ignore')) return false;
  return (Session.get('ignore').indexOf(call)>=0);
}

checkedIn = function(){
  var everyone =  Presences.find().fetch();
  var calls = [];
  var call;
  for(var i=0,l=everyone.length;i<l;++i){
      if ((everyone[i].state) && (everyone[i].userId)){
        call = whoIs(everyone[i].userId);
        if (!ignored(call)) calls.push(call);
      }
  }
  return calls.sort();
};

lastMessages = function(msgCursor, order){
    var last = {}, lastmsgs = [],call='';
    var msgs = msgCursor.fetch();
    for(var i=0,l=msgs.length;i<l;++i){
      call = msgs[i].call;
      if (last[call]){
        if (msgs[i].t>last[call].t){
          last[call] = msgs[i];
        }
      } else {
        last[call] = msgs[i];
      }
    }
    for (k in last){
      if (last.hasOwnProperty(k)) lastmsgs.push(last[k]);
    }
  if (order) lastmsgs.sort(order);
  return lastmsgs;
};

orderBy = function(field, m){
  return function(a,b){
    if (a[field]>b[field]) return m;
    if (a[field]<b[field]) return -m;
    return 0;
  }
};

var PleaseSignIn = function(){
  $( "#dialog-psi" ).dialog({
      modal: true,
      buttons: {
        Ok: function() {
          $( this ).dialog( "close" );
        }
      }
  });
};

var registerHelpers = function(obj){
  for(var k in obj){
    if (obj.hasOwnProperty(k)){
      if (typeof(obj[k])==='function'){
        Template.registerHelper(k, obj[k]);
      }
    }
  }
};

registerHelpers({
  screenHeight: function(){
    return sceeen.height;
  },
  screenWidth: function(){
    return screen.width;
  },
  windowHeight: function(){
    return $(window).height();
  },
  windowWidth: function(){
    return $(window).width();
  },
  msgs: function(){ 
    var query = {call: {$nin: Session.get('ignore')}};
    return Messages.find(query);
  },
  announcements: function(){
    var query = {$and: [{call: {$nin: Session.get('ignore')}},
                        {t: {$gt: (+new Date() - 2*86400000)}},
                                 {txt: {$in: [/^!/]}}
                                ]};
    var msgs =  Messages.find(query);
    return lastMessages(msgs, orderBy('call'));
  },
  lastTransmission: function(){
    var query = {call: {$nin: Session.get('ignore')}};
    return lastMessages(Messages.find(query), orderBy('time', -1));
  },
  checkedIn: function(){
    return checkedIn();
  },
  hms: utcHMS
});

Template.passTable.helpers({
  passes: function(){
    var listOfPasses = PLib.getTodaysPasses();
    listOfPasses.sort(function(a,b){
      return a.dateTimeStart-b.dateTimeStart;
    });
    _depSat.depend();
    // thanks  http://stackoverflow.com/a/18216255/103081 for how to define explicit dependencies
    return listOfPasses;
  }
})

Template.app.events({
  'keyup #ignore': function(event, template){
    Session.set('ignore',$('#ignore').val().replace(/\n/g,' ').split(/[ ,]+/));
  },
 'click .signout': function(event, template){
    if (confirm("thanks 73 was good qso - GO QRT?")){
        Meteor.logout();
        $('.signinEnabled').prop('disabled', true);
        Session.set('callsign','');
    }
  },
  'click .signin': function(event, template){
      var callsign = $('#callsign').val();
      if ((typeof(callsign)==="string") && (callsign.length>2)){
        callsign = callsign.toUpperCase();
        $('#callsign').val(callsign);
        Session.set('callsign',callsign);
        var pass = $('#pass').val();
        var onGoodPassword = function(){
            console.log('good password');
            Meteor.call('chatRegister', callsign, qthxy);
            $('.signinEnabled').prop('disabled',false);          
        };
        Meteor.loginWithPassword(callsign, $('#pass').val(), function(e){
          if (e){
            // if bad password -- do nothing
            if (/password/.test(e.reason)) return false;
            if (/not found/.test(e.reason)){
              if (confirm("[create account] Check callsign for errors. You entered:  "+callsign)){
                Accounts.createUser({'username': callsign, 
                                     'password': <PASSWORD>}, 
                                    function(e){
                                      if (e){
                                        $('#signinWarning').text('bad callsign or password');
                                      } else {
                                        console.log('created user');
                                        onGoodPassword();
                                      }
                                    });

              }
            }
          } else {    
            onGoodPassword();
          }
        });
      }
  },
  'keyup #compose': function(){
    if (!Meteor.userId()){
      // not logged in
      PleaseSignIn();
    } else {
      if ( ($('#compose').val().length>2) && (/\n$/.test($('#compose').val()))  ) {
        $('#send').prop('disabled', true);
        Meteor.call('sendMessage', $('#compose').val() );
        $('#compose').val('');
        setTimeout(function(){
          $('#send').prop('disabled', false);
        }, 1000);      
      }
    }
  },
  'click #satbigger': function(){
    satmag = satmag * 1.5;
  },
  'click #satsmaller': function(){
    satmag = satmag/1.5;
  }
}); 

Template.app.rendered = function(){
  $('#chatBody').tabs();
  if (($.browser) && (!$.browser.mobile)){
    // desktop only
    $('#chatBody').draggable().resizable();    
  }
  Template.app.firstscrollqso = 1;
  $('.firstscrollqso').click(function(){
      if (Template.app.firstscrollqso) scrollToEnd($('#qso .vscroll'));
      Template.app.firstscrollqso = 0;
  });
};

// see http://stackoverflow.com/a/11551414/103081 for scroll to bottom

scrollToEnd = function(j){
  if (j && j.scrollTop) j.scrollTop(j.prop('scrollHeight'));
};

Template.msg.rendered = function(){
    // select the parent of the paragraph elements and scoll to end if scrollable
    var chatDiv = this.$('p').parent('.vscroll'); 
    scrollToEnd(chatDiv);
};

makeWorld = function (){
  var r = Raphael(0, 0, 600, 300);
  world = r.image("/nasa-world-dec.jpg",0,0,600,300);
  world.getXY = function (lat, lon) {
    return {
      cx: lon * (300.0/180.0) + 300.0,
      cy: lat * (-150.0/90.0) + 150.0
    };
  };
  world.getLatLon = function (x, y) {
    return {
      lat: (y - 150.0) / -(90.0/150.0),
      lon: (x - 300.0) / (180.0/300.0)
    };
  };

  try {
    navigator.geolocation && navigator.geolocation.getCurrentPosition(
      function (pos) {
        qthxy = world.getXY(pos.coords.latitude, pos.coords.longitude);
        myQTH = new LatLon(pos.coords.latitude, pos.coords.longitude);
        if (PLib && PLib.configureGroundStation) {
          PLib.configureGroundStation(pos.coords.latitude, pos.coords.longitude);
          _depSat.changed();
        }
      });
  } catch (e) {}

  return {
    'r': r,
    'world': world
  }
};


satTrack = {};

var TrackUpdater = function(){
  Tracker.autorun(function(){
    console.log("fetching satellite tracks");
    var now = Math.floor((+new Date()/1000.0));
    var tracks = Track.find({'end': {$gt: now}}).fetch();
{'fraction_non_alphanumeric': 0.1774211648524296, 'fraction_numerical': 0.016496465043205028, 'mean_word_length': 2.397445672893633, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '598528', 'n_tokens_mistral': 6005, 'n_tokens_neox': 5768, 'n_words': 1266}