Perform a Pluto flyby Congratulations! You've just been hired by NASA to work on the new Horizons 2 project.

Sadly, there have been huge budget cuts recently, so the top management has decided to fake the whole planned Pluto flyby (as they did for the moon landings in the 70s).

Your task is to write a program that will accept as input a date in the format yyyymmdd, and will provide a fake photograph of Pluto for this date. You can assume the entered date will be in the year 2015 or 2016.

The photograph is a 15x15 grid of ASCII characters. The characters on the grid have their x- and y-coordinates within the range [-7, 7] - the top-left character is at (-7, -7) while the bottom-right character is at (7, 7).

The photograph will be computed with the following rules:


The probe will be the nearest to Pluto on 25/12/2015
The distance d to Pluto is given by this formula : square root of ((difference in days to christmas) ^ 2 + 10)
The radius r of Pluto's image on the photo is given by : 22 / d
A character with coordinates (x, y) on the grid must be set to # if x^2 + y^2 &lt;= r^2 ; it must be set to space otherwise.
There are stars at positions (-3, -5), (6, 2), (-5, 6), (2, 1), (7, -2). Stars are represented by a dot ., and they are of course hidden by Pluto.


One more thing: The NASA board has come to the conclusion that the discovery of life on Pluto would likely result in a substantial budget increase. Your program should then add clues of life on Pluto:


When the distance to Pluto is &lt;= 4, add a plutonian at coordinates (-3,-1) : (^_^)


Example photograph for input 20151215: (Your code should have all the newlines as this code does) 

               

    .          


       #      .
      ###      
     #####     
      ###.     
       #     . 



  .            



Photograph for input 20151225:

               
    #######    
   #########   
  ###########  
 ############# 
 #############.
 ###(^_^)##### 
 ############# 
 ############# 
 ############# 
 ############# 
  ###########  
   #########   
  . #######    



As a comparison, here's a photo of Pluto's satellite Hydra as taken by New Horizons. Differences are hardly noticeable with our ASCII art.



This is code golf, so the shortest code in bytes wins!
JavaScript (ES6), 237 bytes

f=(n)=&gt;(t=new Date('201'+n[3],n[4]+n[5],n[6]+n[7])/864e5-403805/24,r=484/(t*t+10),(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;(i*i+j*j&lt;=r?r&gt;30.25&amp;!~i&amp;&amp;'(^_^)'[j+3]||'#':~'p-3-5p62p-56p21p7-2'.indexOf('p'+j+i)?'.':' ')+(++j&lt;8?h(j):''))(-7)+'\n'+g(i):''))(-8))


Live demo. Run in Firefox.

Original version

f=function(n) {
    t = (new Date('201'+n[3],''+n[4]+n[5],''+n[6]+n[7]) // Find the time difference in milliseconds,
    - new Date(2015,12,25)) / 864e5;                    // then divide by 86400000 to convert to days.

    r=22 / Math.sqrt(t*t+10);                           // Calculate the radius.

    s=[]; // s is the array that contains each line as a string.

    for(i=-7;i&lt;8;i++)               // Loop through rows.
        for(j=-7,s[i+7]='';j&lt;8;j++) // Loop through columns, appending one character per column.
                                    // s is zero based, so add 7 to the row.
            s[i+7]+=i*i+j*j&lt;=r*r ?  // Choose which character to add to s. 
            (r&gt;5.5&amp;i==-1&amp;&amp;'(^_^)'[j+3]||'#') :  // Add a '#' if the position is inside the radius.
                                                // If distance &lt; 4, then the radius &gt; 5.5
                                                // Then add the face at the right position.
            {'-3-5':1,'62':1,'-56':1,'21':1,'7-2':1} // Add the stars if outside. Create an associative array.
            [j+''+i]?'.':' ';                        // If i concat j is in the array, the expression will be 1, 
                                                     // which is truthy, else it will be undefined, which is falsey.
    return s.join`\n` // Join all the rows with a new-line.
}


Golfing

This was fun to golf.

I don't need to create a Date object, so I hardcoded the value in milliseconds to save 13 bytes:

t=(new Date('201'+n[3],n[4]+n[5],n[6]+n[7])-new Date(2015,12,25))/864e5 // Before
t=new Date('201'+n[3],n[4]+n[5],n[6]+n[7])/864e5-403805/24 // After


Replace the associative array with a delimited string to eliminate 9 bytes:

{'-3-5':1,'62':1,'-56':1,'21':1,'7-2':1}[j+''+i]?'.':' ' // Before
~'p-3-5p62p-56p21p7-2'.indexOf('p'+j+i)?'.':' ' // After


The biggest refactor was replacing the for loops with nested, recursive IIFEs to knock off 10 bytes:

s=[];for(i=-7;i&lt;8;i++)for(j=-7,s[i+7]='';j&lt;8;j++)s[i+7]+= /* Chooses char at i,j */ ;return s.join`\n` // Before
(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;( /* Chooses char at i,j */ )+(++j&lt;8?h(j):''))(-7)+'\n'+g(i):''))(-8) // After


I also got rid of Math.sqrt for 8 more bytes.

r=22/Math.sqrt(t*t+10),(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;(i*i+j*j&lt;=r*r?r&gt;5.5 // Before
r=484/(t*t+10),(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;(i*i+j*j&lt;=r?r&gt;30.25 // After


Issues

I could only get the correct photograph for the test cases by changing the closest date to 2015/12/24, and I don't know if the problem lies in my code or the question. Please clarify and I will update my answer.

Here is my output using the differences from 2015/12/25.

Edit: Updated answer to use Christmas as the closest date.

Photograph for "20151215":

                   

        .          


           #      .
          ###      
         #####     
          ###.     
           #     . 



      .            
                   

Photograph for "20151225":

                   
        #######    
       #########   
      ###########  
     ############# 
     #############.
     ###(^_^)##### 
     ############# 
     ############# 
     ############# 
     ############# 
      ###########  
       #########   
      . #######