Sunday, November 24, 2019

Tesla Cybertuck, load, and wind-resistance. A lesson in energy.

This week, Tesla unveiled their new Cybertruck, a long anticipated all electric pickup truck.

Some are calling this an F-150 competitor, thinking this is a workhorse truck. However, I think this car is more of a bad-ass vanity truck, competitive with the F-150 Raptor, for guys and gals who want to feel like they're driving an awesome machine but don't actually do that much work with it. Why?

LOAD and WIND RESISTANCE.

Tesla claims a 500 mile range on the Cybertruck, but let me tell you two little stories.

I routinely make the 200 mile trip from San Francisco to Lake Tahoe, California -- In a Lincoln Navigator. We have a Tesla model S, but we never take it to Tahoe. Because the 75 mile uphill trip into the Sierra mountains, takes over 150 miles of range, putting the trip at the uncomfortable limit of range even for the highest capacity cars. Our friends with Teslas stop at the supercharger, every time.

Why? It turns out that Tesla's cars make their range as much by lowering consumption as by increasing capacity, and there just isn't any way to to make hauling a 5000 lb car uphill any more efficient. Load matters. 

However, that's only half the story.. A friend of mine tried to bring his Tesla S to Tahoe, with three bicycles on the roof. Wind resistance is another big part of efficiency, and we've heard all about how the Tesla S and X are designed to have minimum drag. Well, not so when you stick two bicycles on the roof. He could barely make it 100 miles on a charge, and couldn't even make it to the first supercharger. He had to stop at a 110v outlet, to add some extra juice, to get to the first supercharger. Then, realizing this wasn't going to work all the way to Tahoe, they somehow managed to squeeze three bicycles in the back of the model S with three adults inside. And after all these shenanigains, a second supercharger stop (for juice to make it up the sierra grade), and some traffic, it took them 10 hours to reach Tahoe.  Not fun for anyone. My Navigator drive was 3.5 hours non-stop.

What do pickup truck owners do? They drive around with open beds, that have massive drag, often with stuff inside, sometimes hauling trailers. It's good Tesla juiced the Supertruck up with 500 miles of range, because when the bed is open creating drag, you're going to get alot less range. If you pull a trailer, I'd be shocked to see it get 200 miles, and if you're dragging it all up the Sierra Grade, good luck.

I love my Tesla. I love Electrics. However, it's really important to understand that every tool is not right for every job.

The Tesla Supertruck has polarizing styling, and is sure to have amazing performance. I think it may play well in the vanity semi-luxury style truck market, such as consumers buying F-150 Raptors and Jeep Rubicons to do their suburban and city driving in. However, if you want a working truck to carry big hauls, and pull big loads even medium distances, I don't think an electric pickup truck is your cup of tea - yet.


ideas for battling FPS cheaters

A constant plague on First Person Shooter games is cheaters. In particular, ESP cheats, which allow players to see enemies through walls, and aimhacks, which allow players to auto-aim or auto-headshot enemies.

These cheats make these games very unpleasant to play, because over time a significant fraction, possibly as many as 30% of online players, end up cheating.

I've spent lots of time thinking about how to combat cheaters, and it's a very tough problem. Some have talked about game-streaming as a possible solution, but the latency and latency variability of game-streaming is currently horrible.

Another possibility is some kind of protected execution, but this would require not only support from the operating system, but also potentially support from the GPU, to prevent nefarious hacks from being injected into the process and/or GPU shaders.

Here are two ideas which could be deployed today, to fight FPS cheaters...
  • Aim-Captcha challenge - have the game challenge players with very good aim, with some kind of server-rendered video "aim test". if they can't score a decent level on it, then put the recent games into an aimhack review queue.
  • ESP "ghosts" - Have the game server inject a fairly decent number of "fake", but (mostly) fully occluded players. So ESP hackers are chasing ghosts.
Here is some more detail about each idea... They are published here to be free for all to use.

Aim-Captcha challenge - If a player registers above a certain percentage of headshots and/or hits, when shooting generally towards targets (ignoring random shots into nowhere), after the game is over, give them some kind of captcha-inspired aim-challenge, which is somehow not bottable.. Perhaps by sending a 360VR video, where they have to dispatch targets with reasonable precision. If they don't hit some reasonable precision target, then they're put into a queue for recent game replays to be evaluated for aim-hacking.

This is inspired by how https://play.typeracer.com (an online typing speed test) fights OCR cheaters. On that site, if you score above 100wpm, they give you another typing test which is a fully paragraph of captcha text, asking you to type that fast. This tries to assure a human is reading and doing the typing, isntead of an OCR bot. (I know it seems hard to believe someone would cheat an online typing test with OCR, but if there is a game online, people will cheat)


ESP "ghosts" -  Basically, the game could inject a bunch of noisy fake players, fully occluded by walls, that only ESP hackers would see. Effectively, this would make them chase ghosts. At worst, this would make their ESP unreliable, because they would never know what markers were real enemies, and what markers were fake enemies. At best, an algorithm might be able to determine when players are consistently chasing after fake occluded enemies, and automatically ban them.

Of course it's important that the fake enemies not confuse non-cheating players. So these fake enemies should not make sounds. The only sign of their existance should be the draw commands to the GPU to render a character, and in this respect they should be indistinguishable from real players. It's also important not to give them easily detectable patterns. For example, they shouldn't be in the same exact spots. They shouldn't be exactly stationary.

Perhaps a decent method would be to mark indoor locations that are invisible or nearly invisible from ranges of 10-1000m, and record real player behavior in these locations. In later games, that player behavior could be "replayed" as an ESP ghost.

In order for this technology to work, the game must have some kind of partial visibility from the server. Otherwise the "sudden appearance" of an ESP ghost would be a telltale sign it's not a real player. This could be simply range-based partial visibility, or it could be something more complex.


Wednesday, October 23, 2019

Google Apps Script for Advanced Gmail Filtering

TLDR - I just found and used Google Apps Script to write a really cool Gmail filter, that stars any thread (into a separate star-section) that is from someone that I've sent email to before. (i.e. senders I actually know)

Google Apps Script is an online typescript IDE that lets you script together apps at google.. It's kind of terribly clunky and buggy, but it also is pretty amazing that there is some Intellisense in a browser, and this thing is now seamlessly running in the cloud every 30 minutes.

Here are some instructions for setting up Google Apps Script. My filtering script is below..

Why did I do this?

I finally reached a threshold with all the non-spam notification mail cluttering up my inbox.

I already have multiple-inbox sections configured, with starred messages in a different section on top. I used to manually create filters to star messages, from my boss, or my wife.. but this doesn't really scale.



What I've always wanted was to automatically star threads from people in my contacts, or people I've sent email to before. However, gmail filters can't do this.

Enter Google Apps Script. It's a generalized cloud hosted Typescript programming environment, where you can bind together scripted actions on Google products. Some of it is a big laggy and clunky, a bit like dealing with the world's slowest compiler, and a debugger that is broken. However, now that the script is working, it's pretty neat that this is all magically hosted in the cloud and running every 30 minutes.

Here is my script:



function prioritizeInbox() {
    
  console.log("code start...");
  
  // var firstThread = GmailApp.getInboxThreads(0,1)[0];
  var firstThread = GmailApp.search("in:inbox and (label:starred)", 0, 1)[0];
  firstThread.markUnread();  
   
  // Wrap the entire function in a try / catch, in case there is an error, log it.
  try {
   
    // Get the most recent threads in your inbox
    var NUM_THREADS = 50;
    var threads = GmailApp.search("in:inbox and (!label:starred)", 0, NUM_THREADS);
    
    console.log("fetched threads ... " + threads.length);
    // For each thread
    for (var t=0; t<threads.length; t++) {
      var thread = threads[t];
      console.log({msg:"thread", n:t, thread:thread});
      
      // Get the sender of the thread
      var senders_map = {};
      var messages = thread.getMessages(); 
      for (var msg_n in messages) {          
        var msg = messages[msg_n];
        var msg_sender = extractEmail(msg.getFrom());
        senders_map[msg_sender] = 1;
      }
      
      var senders = Object.keys(senders_map);
      
      console.log("thread senders : " + senders);
      
      for (var n in senders) {
        var sender = senders[n];
        console.log("checking sender : " + sender);
        if (isImportantSender(sender)) {
          console.log("*****   Starring message from .. " + sender + "     ******");
          
          GmailApp.starMessage(messages[0]);       // star the first message in thread   
          break;
        }
      }       

      
    }
  } catch (e) {
    console.log("Error..." + e.toString());
  }
}


function isImportantSender(sender) {
      
  // check user email
  
  var user_email = Session.getActiveUser().getEmail();
  // console.log("checking user email ... " + user_email);
  if (sender == user_email) {
    return true;
  } 
  
  // check gmail aliases
  var aliases = GmailApp.getAliases();
  // console.log("aliases... " + aliases);
  for (var n in aliases) {
    // console.log("checking alias: " + aliases[n]);                     
    if (sender == aliases[n]) {
      return true;
    }          
  }
  
  if (false) {
    // check if I they are in my starred folder
    var search_spec = "label:starred from:" + sender;
    console.log("starred search_spec = " + search_spec);
    var starred_threads = GmailApp.search(search_spec,0,5);
    if (starred_threads.length > 4) {
      return true;
    } 
  }
    
  // check if i've sent them mail twice before
  var search_spec = "from:me to:" + sender;
  console.log("convo search_spec = " + search_spec);
  var chats_with_contact = GmailApp.search(search_spec,0,5);
  console.log("chats_with_contact .... " + chats_with_contact.length)
  if (chats_with_contact.length > 1) {
    return true;
  }   
  
  return false;
}

function extractEmail(addr) {    
  var regex  = new RegExp("^[^<> '\"]@[^<> \"']$");  
     
  if (regex.test(addr)) {
    return addr;
  }
    
  var regex2 = new RegExp("^.+<([^ ]+@.+)>$");
  if (regex2.test(addr)) {
    var match = regex2.exec(addr);
   
    return match[1];
  }
  
  return addr;
  
  
}