ASCII Art "Flight Simulator"

24

MODIFIER

Il semble qu'il y ait eu une certaine confusion à la suite de ma faute de frappe dans le message d'origine qui utilisait un o minuscule pour définir le plan, puis un majuscule plus tard. Malheureusement, ce bug n'a pas été détecté dans le bac à sable. Étant donné que de nombreux membres ont écrit des réponses avec les deux et que la faute de frappe était de ma faute, j'autoriserai les majuscules ou les minuscules dans la définition de l'avion. J'ai ajouté une nouvelle règle pour cela.

Contexte

J'aime les animations d'art ascii comme j'ai tendance à les appeler alors en voici une autre. Je ne pense pas que ce soit trop difficile à mettre en œuvre, nous espérons donc obtenir des réponses courtes et intéressantes.

À tous les autres membres de la communauté

Si vous améliorez votre réponse, veuillez modifier votre nombre d'octets comme

ancien décompte d' octets nouveau décompte d'octets

afin que nous puissions voir vos progrès. Merci!

Défi

Voici un plan ascii

--O--

Voici une piste ascii

____|     |____

L'avion démarre à 5 nouvelles lignes au-dessus de la piste. Pour éviter tout affrontement entre les systèmes métriques et impériaux et en faire un véritable défi international, je ne mentionnerai pas les mètres ou les pieds. Exemple:

        --O--




____|     |____

L'avion doit atterrir exactement au milieu de la piste comme indiqué ci-dessous:

____|--O--|____

Contribution

La position horizontale initiale du plan est définie par une entrée entière qui est utilisée pour référencer la pointe de l'aile gauche, c'est-à-dire qu'elle est comprise entre 0 et 10 inclus.

Sortie

Chaque étape du vol des avions doit être montrée. Exemple ci-dessous (entrée = 10):

          --O--




____|     |____

         --O--



____|     |____

        --O--


____|     |____

       --O--

____|     |____

      --O--
____|     |____

____|--O--|____

Pour simplifier les choses, nous ignorons les lois de la perspective. La piste reste de la même taille à mesure que vous vous rapprochez.

Règles

  • Mise à jour Le milieu de l'avion peut être un o majuscule ou minuscule, mais celui qui est choisi doit être cohérent dans tout le code. Si votre langue ne prend pas en charge les caractères ci-dessus, n'hésitez pas à utiliser uniquement des caractères ascii alternatifs.
  • L'avion descend 1 ligne par image.
  • L'avion ne peut se déplacer que d'un espace vers la gauche ou la droite chaque fois qu'il descend d'une ligne. Il n'a pas à se déplacer sur chaque ligne de descente. Tant qu'il se termine sur la piste, c'est à vous de décider quand il se déplace à droite ou à gauche. Tu es le pilote!
  • Aucune gestion des erreurs requise. Vous pouvez supposer que l'entrée sera toujours un entier valide de 0 à 10 inclus.
  • La sortie doit être composée uniquement des caractères indiqués ci-dessus (si votre langue ne les prend pas en charge, voir la première règle éditée) et doit être de la même taille, c'est-à-dire qu'elle doit commencer 6 lignes de haut par 15 caractères de large. La hauteur peut diminuer à mesure qu'elle progresse comme dans l'exemple ci-dessus.
  • Le programme ou la fonction est correct mais doit produire une sortie comme indiqué ci-dessus.
  • Les espaces de début / fin / les nouvelles lignes me conviennent.
  • N'hésitez pas à effacer l'écran entre les images de sortie si vous le souhaitez. Ce n'est pas une exigence.
  • Les failles standard interdites comme d'habitude (bien que je ne pense pas qu'il y en ait beaucoup qui aideraient à ce genre de défi).
  • Il s'agit du code golf, donc la réponse la plus courte est évidemment la gagnante et obtiendra probablement la plupart des votes, mais ne sera pas nécessairement acceptée comme la meilleure réponse si une solution vraiment intéressante se présente dans un langage inattendu, même si elle est plus longue. N'hésitez pas à publier tout ce qui respecte les règles tant qu'il fonctionne.

Implémentation de référence non golfée dans Python 2 disponible sur Try it online! afin que vous puissiez voir à quoi il ressemble pour différentes valeurs d'entrée.

ElPedro
la source
Je ne pense pas que ce soit kolmogorov-complexité car la sortie dépend de l'entrée
ovs
Merci pour la clarification @ovs. Je supprimerai alors cette balise.
ElPedro
Habituellement, l'acceptation va à la réponse qui correspond le mieux au critère de gain objectif. Vous pouvez obtenir un flak si vous acceptez une autre réponse plus longue.
Level River St
Merci @LevelRiverSt. Existe-t-il un meta post pour clarifier cela? Sinon, il vaut peut-être mieux ne pas accepter de réponse.
ElPedro
btw, j'ai déjà accepté une réponse plus longue et j'ai attribué la réponse la plus courte sans aucun problème de la communauté Défi précédent . Veuillez voir mon commentaire de résultat à la fin de la question. C'était mal?
ElPedro

Réponses:

5

TI-BASIC, 61 octets

Input A
A
For(B,1,5
ClrHome
Output(5,1,"----/     /----
Output(B,Ans,"--O--
Ans+6-median({5,7,Ans
End
Julian Lachniet
la source
Connaissez-vous un interprète en ligne ou téléchargez-le (pour Linux) pour les tests? +1 pour la réponse en supposant que cela fonctionne :)
ElPedro
Découvrez TilEm. C'est le seul que j'ai pu travailler.
Julian Lachniet
2
+1 pour avoir demandé à quelqu'un qui aurait pu avoir une réponse différente. Va certainement vérifier TilEm et merci pour l'astuce.
ElPedro
8

TI-BASIC, 62 octets

:Input A
:A
:For(N,3,8
:ClrHome
:Output(8,1,"----I     I----
:Output(N,Ans,"--O--
:Ans+(Ans<6)-(Ans>6
:End

Notez que TI-BASIC ne prend pas en charge _ ou | et donc j'ai remplacé par un I majuscule et -. Cela ne devrait pas affecter le nombre d'octets.

Nombre d'or
la source
OK, je suis sous Linux. Pouvez-vous recommander un téléchargement pour tester cela? btw, je suppose que cela fonctionne jusqu'à ce que je trouve un interprète donc +1 :)
ElPedro
Malheureusement non. J'ai Wabbitemu et TilEm installés sur mon ordinateur Windows 10, mais je teste le code sur une TI-84 + physique. Désolé
Golden Ratio
Aucun problème! Je demande juste :)
ElPedro
En raison de beaucoup d'édition de code, le plus rapide a alterné entre ce post et celui de Julian Lachniet, jusqu'à ce que nous arrivions tous les deux à la conclusion de 60 octets, auquel point j'ai ajouté clrhome et fait le nombre d'octets 62
Golden Ratio
3
TI-Basic?! Agréable!
Dave Kanter
6

Python 2, 107 octets

n=input();h=5
while h:print' '*n+'--O--'+'\n'*h+'____|     |____\n';n-=cmp(n,5);h-=1
print'____|--O--|____'

Essayez-le en ligne

Codez simplement en dur la dernière ligne de l'avion d'atterrissage. Il peut probablement être joué au golf en réutilisant des pièces antérieures ou en étant intégré à la boucle.

xnor
la source
5

Perl, 94 octets

93 octets de code + -pindicateur.

$\="____|     |____
";$p="--O--";for$i(-5..-1){print$"x$_.$p.$/x-$i;$_+=5<=>$_}$\=~s/ +/$p/}{

Essayez-le en ligne!

Dada
la source
@ETHproductions J'espère que vous apprécierez le }{(et le $"dérangement avec la coloration syntaxique).
Dada
3

JavaScript (ES6), 108 octets

f=(a,b=5)=>b?" ".repeat(a)+`--O--${`
`.repeat(b)}____|     |____

`+f(a<5?a+1:a-1,b-1):"____|--O--|____"

Essaye-le

Usage

Il suffit d'appeler favec l'index de l'avion.

f(2)

Sortie

  --O--




____|     |____

   --O--



____|     |____

    --O--


____|     |____

     --O--

____|     |____

    --O--
____|     |____

____|--O--|____
Luc
la source
Vous pouvez ajouter un <s> snack </s> extrait de pile
Kritixi Lithos
Chaque fois que je pose une question, la première réponse est Javascript! +1
ElPedro
Hé, ce serait bien si les gens publiaient soit une Tryitonline (je ne sais pas si c'est possible avec Javascript) ou une solution différente de l'exemple 10 ci-dessus. Pouvez-vous publier la sortie de par exemple 2 à la place? :)
ElPedro
@ElPedro, vous pouvez exécuter JavaScript dans la console de votre navigateur, mais il existe également des consoles en ligne. Je vais ajouter un lien. Je vais également changer l'exemple.
Luke
Merci. Pas de problème. Je suis dans l'ancien Javascript où vous avez besoin d'une page Web pour l'exécuter. Je suppose que je dois faire avec le temps :) Plus côté serveur ces jours-ci. Respect de la réponse rapide et cool.
ElPedro
3

Scala, 224 181 octets

EDIT : Je ne savais pas que vous pouviez faire "string"*npour le répéter n fois! Scala continue de me couper le souffle. Manquer le if(t>0)au lieu de if(t==0)était une erreur de débutant. Merci pour les conseils, Suma !


def?(x:Int,t:Int=5):Unit={var(p,o)=("--o--","")
o=s"____|${if(t>0)" "*5 else p}|____\n"
for(i<-0 to t)o=if(i!=0&&i==t)" "*x+p+o else "\n"+o
println(o)
if(t>0)?(x-(x-4).signum,t-1)}

Remarques originales:

J'ai pensé qu'une solution récursive serait amusante à essayer. Je suis relativement nouveau à Scala, donc je suis certain que c'est loin d'être optimal.

Archimage se tient avec Monica
la source
Vous voudrez peut-être lire Conseils pour jouer au golf à Scala
corvus_192
Vous n'en avez pas besoin :Unit=. L'omission du signe égal définira le type de retour sur Unité.
corvus_192
Aussi, pourquoi n'avez-vous pas initialisé odans la première ligne?. Et comme ic'est toujours> = 0, vous pouvez passer i!=0&&i==tà i>0&i==t(3e ligne).
corvus_192
2

Lot, 230 octets

@echo off
set/ax=10-%1
set s=          --O--
for /l %%i in (0,1,4)do call:l %%i
echo ____^|--O--^|____
exit/b
:l
call echo %%s:~%x%%%
for /l %%j in (%1,1,3)do echo(
echo ____^|     ^|____
echo(
set/a"x-=x-5>>3,x+=5-x>>3

xest le nombre d'espaces à supprimer depuis le début de la chaîne s, donc je soustrais le paramètre à 10. La dernière ligne est le lot le plus proche x-=sgn(x-5).

Neil
la source
2

sed, 181 octets + 2 pour les -nrdrapeaux

s/10/X/
:A
s/^/ /;y/0123456789X/-0123456789/;/[0-9]/bA;s/ -/P\n\n\n\n\n____|P|____/
:B
h;s/P([\n|])/--O--\1/;s/P/     /;s/^ *_/_/;p;/^_/q;x;s/\n//
/^ {5}$/bB;/ {6}/s/  //;s/^/ /;bB

Non golfé

# Add leading spaces
s/10/X/
:A
    s/^/ /
    y/0123456789X/-0123456789/
/[0-9]/bA

s/ -/P\n\n\n\n\n____|P|____/

:B
    # Place plane in appropriate spot
    h
    s/P([\n|])/--O--\1/
    s/P/     /
    s/^ *_/_/
    p
    /^_/q
    x

    # Movement
    s/\n//
    /^ {5}$/bB
    # move left one extra, since we'll move right next line
    / {6}/s/  // 
    s/^/ /
bB

Usage: $ echo 2 | sed -nrf flightsim.sed

Rayon
la source
2

Rétine , 86 83 octets

.+
$* --O--¶¶¶¶¶¶____|     |____
{*`$
¶
2D`¶
 ( {5})
$1
}`^ {0,4}-
 $&
 +
--O--
G`_

Essayez-le en ligne!

Il y a probablement une sorte de compression que j'aurais pu utiliser sur la piste et l'espace vide au-dessus, mais tout ce que j'ai essayé est venu plus cher que le texte en clair (dans Retina ¶ est une nouvelle ligne, donc vous pouvez voir l'état initial en texte clair sur le deuxième ligne).

Leo
la source
2

Scala , 177, 163, 159 137 octets

def p(x:Int,t:Int=5,a:String="\n"):String=a+(if(t>0)
" "*x+"--O--"+"\n"*t+"____|     |____\n"+p(x-(x-4).signum,t-1)else"____|--O--|____")

Basé sur une autre réponse , avec des réductions importantes.

Suma
la source
2

Perl 6 , 97 90 81 octets

{say "{"{" "x 15}\n"x 5}____|     |____"~|("\0"x$^h+$_*(17-$h/5)~"--O--") for ^6}

Contrairement à ce à quoi il ressemble, il génère la version * en minuscule du plan ( --o--), comme le permet la description de tâche mise à jour.

Essayez-le en ligne!

Comment ça marche

Opérateurs de chaîne de bits FTW!

{                                                  # Lambda accepting horizontal index $h.
    say                                            # Print the following:
        "{ "{ " " x 15 }\n" x 5 }____|     |____"  # The 15x6 background string,
        ~|                                         # bitwise-OR'd against:
        (
            "\0"                                   # The NULL-byte,
            x $^h + $_*(17 - $h/5)                 # repeated by the plane's offset,
            ~ "--O--"                              # followed by an OR mask for the plane.
        )
    for ^6                                         # Do this for all $_ from 0 to 5.
}

Cela fonctionne car les opérateurs de chaîne au niveau du bit utilisent les valeurs de point de code des caractères à une position donnée dans deux chaînes, pour calculer un nouveau caractère à cette position dans la chaîne de sortie.
Dans ce cas:

space  OR  O   =  o
space  OR  -   =  -
any    OR  \0  =  any

Pour un Oplan en majuscules , nous aurions pu utiliser ~^(chaîne XOR au niveau du bit), avec un masque de plan de \r\ro\r\r(+4 octets pour les contre-obliques):

space  XOR   o  =  O
space  XOR  \r  =  -
any    XOR  \0  =  any

La formule du décalage de l'avion h + v*(17 - h/5), a été simplifiée à partir de:

  v*16         # rows to the vertical current position
+ h            # columns to the horizontal starting position
+ (5 - h)*v/5  # linearly interpolated delta between horizontal start and goal
smls
la source
1

Python 2 , 160 octets

i,s,p,l,r,c,x=input(),' ','--O--','____|','|____',0,4
while x>=0:print'\n'.join([s*i+p]+[s*15]*x+[l+s*5+r])+'\n';c+=1;x-=1;i=((i,i-1)[i>5],i+1)[i<5]
print l+p+r

Essayez-le en ligne!

Voici l'implémentation de référence qui a baissé à 160 contre 384. Encore du chemin à faire je pense. Juste publié pour le plaisir et pour encourager une meilleure réponse Python.

ElPedro
la source
Vous pouvez participer à votre propre défi (voir cette méta-publication ).
Dada
Tu peux juste faire while-~x?
FlipTack
Je pense aussi que vous pouvez écrire le bit où vous ajoutez ou soustrayez de iasi+=(i<5)-(i>5)
FlipTack
1

Befunge-93, 136 130 octets

&5>00p10p55+v
:::00g>:1-\v>:"____|     |_"
>:1-\v^\+55_$"--O--"10g
^\*84_$>:#,_10g::5v>:#,_@
<_v#!:-1g00+`\5\-`<^"____|--O--|____"

Essayez-le en ligne!

Explication

&                          Read the plane position.
 5                         Initialise the plane height.
  >                        Begin the main loop.

   00p                     Save the current height.
      10p                  Save the current position.
         55+:              Push two linefeed characters.

         "____|     |_"    Push most of the characters for the airport string.
:::                        Duplicate the last character three times to finish it off.

   00g>:1-\v               Retrieve the current height, and then push
      ^\+55_$                that many copies of the linefeed character.

             "--O--"       Push the characters for the plane.

>:1-\v              10g    Retrieve the current position, and then push
^\*84_$                      that many copies of the space character.

       >:#,_               Output everything on the stack in reverse.

            10g::          Retrieve the current position and make two copies to work with.
                 5v        If it's greater than 5
                -`<          then subtract 1.
           +`\5\           If it's less than 5 then add 1.

        g00                Retrieve the current height.
      -1                   Subtract 1.
 _v#!:                     If it's not zero, repeat the main loop.

^"____|--O--|____"         Otherwise push the characters for the landed plane.
>:#,_@                     Output the string and exit.
James Holderness
la source
1

Rubis, 94 octets

->a{5.times{|i|puts" "*a+"--O--#{?\n*(5-i)}____|     |____

";a+=5<=>a};puts"____|--O--|____"}

Imprime la position de l'avion suivie de nouvelles lignes puis de l'aéroport. Il déplace ensuite l'avion de 1, -1 ou 0, selon sa position par rapport à 5.

Après avoir bouclé les 5 fois ci-dessus, il imprime l'avion à l'aéroport.

IMP1
la source
1

8ème , 177 172 octets

: f 5 >r 5 repeat over " " swap s:* . "--O--" . ' cr r> times "____|     |____\n\n" . over 5 n:cmp rot swap n:- swap n:1- dup >r while "____|--O--|____\n" . 2drop r> drop ; 

Le mot fattend un entier compris entre 0 et 10.

Usage

4 f

Explication

: f \ n --
  5 >r     \ Push vertical distance from airport to r-stack
  5 repeat 
    \ Print plane
    over " " swap s:* . "--O--" . 
    \ Print airport 
    ' cr r> times "____|     |____\n\n" . 
    \ Now on the stack we have:
    \ distanceFromLeftSide distanceFromAirport
    over      \ Put distance from left side on TOS 
    5 n:cmp   \ Compare left distance and 5. Return
              \ -1 if a<b, 0 if a=b and 1 if a>b
    rot       \ Put distance from left side on TOS   
    swap n:-  \ Compute new distance from left side 
    swap n:1- \ Decrement distance from airport
    dup >r    \ Push new airport-distance on the r-stack  
  while 
  "____|--O--|____\n" .  \ Print final step
  2drop r> drop          \ Empty s-stack and r-stack
;
Manoir du Chaos
la source
1

Mathematica, 111 octets

If[#<1,"____|--O--|____"," "~Table~#2<>"--O--"<>"
"~Table~#<>"____|     |____

"<>#0[#-1,#2+#2~Order~5]]&[5,#]&

Fonction anonyme. Prend un nombre en entrée et renvoie une chaîne en sortie. Pourrait probablement être joué au golf plus loin.

LegionMammal978
la source
1

QBIC , 93 91 84 octets

:{X=space$(a)+@--O--`┘a=a-sgn(a-5)~t>-1|?X[t|?]t=t-1?@____|`+@     `+_fB|\_xB+A+_fB

Suppression de quelques octets en remplaçant la déclaration de X $; optimisé la boucle FOR qui imprime la distance au-dessus du sol. L'explication ci-dessous concerne l'ancienne version, mais elle fonctionne essentiellement de la même manière.

Pour les tests (et l'esthétique) j'avais une version légèrement différente, à 103 octets:

:{_z.5|_CX=Y[a|X=X+@ `]X=X+@--O--`
a=a-sgn(a-5)
~u>0|?X';`[u|?]u=u-1?@____|`+@     `+_fC|\_xC+_tB+_fC

Ceux-ci sont fonctionnellement identiques. Le second a en plus que l'écran est effacé entre les images et qu'il s'arrête pendant 0,5 seconde entre les images.

Exemple de sortie

Notez que j'ai ajouté deux nouvelles lignes entre les images. Le code le plus joué ci-dessus n'ajoute pas de lignes vides entre les images, la plus froide efface l'écran.

Command line: 10


          --O--




____|     |____


         --O--



____|     |____


        --O--


____|     |____


       --O--

____|     |____


      --O--
____|     |____


____|--O--|____

Explication

Comme je pense que cela touche à beaucoup de choses que j'aime vraiment à propos de QBIC et donne un bon aperçu de la façon dont certaines de ses fonctions fonctionnent sous le capot, je suis allé un peu trop loin dans l'explication. Notez que QBIC est, à sa base, un interpréteur QBasic pour Codegolf. Le code QBIC entre - Le code QBasic sort (et est ensuite exécuté).

:{      get the starting offset (called 'a') from the command line, and start a DO-loop

----  cool code only  ----
_z.5|_C At the start of a DO-loop, pause for half a second and clear the screen
---- resume golf-mode ----

---- #1 - The tip of the left wing is anywhere between 0 and 10 positions to the right.
----       Create the plane with the spacing in X$
X=Y          Clear X$
[a|          For each point in the current offset
X=X+@ `]     Add a space to X$
    - Every capital letter in QBIC references that letter+$, a variable of type String
    - @ and ` start and end a string literal, in this case a literal space.
    - ] ends one language construct (an IF, DO or FOR). Here, it's NEXT
X=X+@--O--`  Create the actual plane
    - @ and `once again create a string literal. Every literal that is created in this
      way is assigned its own capital letter. This is our second literal, so the body of
      our plane is stored in B$ (A$ contains the space, remember?)

---- #2 Adjust the offset for the next iteration      
a=a-sgn(a-5) The clever bit: We have an offset X in the range 0 - 10, and 5 attempts to 
             get this to be == 5. X - 5 is either positive (X = 6 - 10), negative 
             (X = 0 - 4) or 0 (X=5). sgn() returns the sign of that subtraction 
             as a 1, -1 or 0 resp. We then sub the sign from 'a', moving it closer to 5.

---- #3 Draw the plane, the empty airspace and the landing strip             
~u>0|     Are we there yet?
    - ~ is the IF statement in QBIC
    - It processes everything until the | as one true/false expression
    - All the lower-case letters are (or better, could be) references to numeric 
      variables. Since QBasic does not need to post-fix those, they double as 'natural' 
      language: ignored by QBIC and  passed as literal code to the QBasic beneath.
    - The lower-case letters q-z are kinda special: at the start of QBIC, these 
      are set to 1 - 10. We haven't modified 'u' yet, so in the first DO-loop, u=5

?X';`     If we're still air-borne, print X$ (our plane, incl. spacers)
    - ? denotes PRINT, as it does in QBasic.
    - ' is a code literal in QBIC: everything until the ` is not parsed, but 
      passed on to QBasic.
    - In this case, we want a literal ; to appear after PRINT X$. This suppresses 
      QBasic's normal line-break after PRINT. This needs to be a code literal 
      because it is the command to read a String var from the command Line in QBIC.
[u|?]     FOR EACH meter above the ground, print a newline
u=u-1     Descent 1 meter
?@____|`  Print the LHS of the landing strip
+@     `  plus 5 spaces
+_fC|     plus the LHS reversed.
\         ELSE - touchdown!
_x        Terminate the program (effectively escape the infinite DO-loop)
    - the _x command has an interesting property: ULX, or Upper/Lowercase Extensibility. 
      Writing this command with an uppercase _X does something similar, yet different. 
      The _x command terminates, and prints everything found between _x and | before 
      quitting. Uppercase _X does not look for |, but only prints something if it is 
      followed by a character in the ranges a-z and A-Z - it prints the contents of 
      that variable.
C+B+_fC   But before we quit, print C$ (the LHS of the landing strip) and the plane, 
          and the LHS flipped.

---- #4 QBIC has left the building
- Did I say _x looks for a | ? Well, that gets added implicitly by QBIC at the end of 
  the program, or when one ( ']' ) or all ( '}' ) opened language constructs are closed.
- Also, all still opened language constructs are automatically closed at EOF.
- Had we stored anything in Z$, that would also be printed at this time.
steenbergh
la source
1

SmileBASIC, 109 105 octets

G$="_"*4INPUT X
FOR I=0TO 4?" "*X;"--O--";CHR$(10)*(4-I)?G$;"|     |";G$X=X-SGN(X-5)?NEXT?G$;"|--O--|";G$
12Me21
la source
1

PHP 7, 139 octets

toujours terriblement long

for($x=$argv[1],$d=6;$d--;$x+=5<=>$x)for($i=$p=-1;$i++<$d;print"$s
")for($s=$i<$d?" ":"____|     |____
";!$i&++$p<5;)$s[$x+$p]="--O--"[$p];

prend l'entrée de l'argument de la ligne de commande; courir avec -r.

panne

for($x=$argv[1],                        // take input
    $y=6;$y--;                          // loop height from 5 to 0
    $x+=5<=>$x)                             // post increment/decrement horizontal position
    for($i=$p=-1;$i++<$y;                   // loop $i from 0 to height
        print"$s\n")                            // 3. print
        for($s=$i<$y?" ":"____|     |____\n";   // 1. template=empty or runway+newline
            !$i&++$p<5;)$s[$x+$p]="--O--"[$p];  // 2. if $i=0, paint plane
Titus
la source